zoukankan      html  css  js  c++  java
  • IPC通信:Posix信号灯

      信号灯用来实现同步——用于多线程,多进程之间同步共享资源(临界资源)。信号灯分两种,一种是有名信号灯,一种是基于内存的信号灯。有名信号灯,是根据外部名字标识,通常指代文件系统中的某个文件。而基于内存的信号灯,它主要是把信号灯放入内存的,基于内存的信号灯,同步多线程时,可以放到该多线程所属进程空间里;如果是同步多进程,那就需要把信号灯放入到共享内存中(方便多个进程访问)。

      有名信号灯和基于内存的信号灯,具体区别体现在创建和销毁两个函数。有名信号灯使用sem_open和sem_close函数。基于内存的信号灯使用sem_init和sem_destroy函数。sem_init的参数可以控制是同步多线程,还是多进程;且该函数只能调用1次,因为调用后信号灯就存在了( 内存指针存在)。一般,使用基于内存的信号灯同步同进程多线程,使用有名信号灯同步多进程。

    有名信号灯同步多线程:

     1 1.sem_open函数。
     2 功能:创建并初始化信号灯,如果存在就返回存在的信号灯。
     3 头文件:#include <semaphore.h>
     4 函数原型:sem_t * sem_open(const char * name,int oflag,mode_t mode,unsigned int value);
     5    或者:sem_t * sem_open(const char * name,int oflag);
     6 参数:name是给信号灯指定一个名字。oflag的值为O_CREAT,表示如果信号灯不存在,创建信号灯;为O_CREAT|O_EXCL,如果信号灯不存在报错。后面两个参数,只有新建信号灯时使用。mode为信号灯的权限(0644),value为信号灯的值。
     7 返回值:成功时,返回信号灯的指针,错误返回SEM_FAILED
     8 
     9 2.sem_close函数。
    10 功能:关闭引用信号灯,信号灯引用计数减1。
    11 头文件:#include <semaphore.h>
    12 函数原型:int sem_close(sem_t * sem)
    13 参数:sem为信号灯的指针
    14 返回值:成功时,返回0,失败,-1
    15 注:每个信号灯有一个引用计数器记录当前打开次数.关闭一个信号灯并没有将它从系统中删除,而是信号灯引用计数减1
    16 
    17 
    18 3.sem_unlink函数
    19 功能:信号灯引用计数为0时,从系统中删除信号灯。
    20 头文件:#include <semaphore.h>
    21 函数原型:int sem_close(const char *name)
    22 参数:name为信号灯的外部名字
    23 返回值:成功时,返回0,失败,-1
    24 
    25 4.sem_wait/sem_trywait函数
    26 功能:等待共享资源,信号灯值为0就睡眠,信号灯值大于0,就使用共享资源,信号灯值减1。sem_trywait当信号灯值为0时,不睡眠,报错。
    27 头文件:#include <semaphore.h>
    28 函数原型:int sem_wait(sem_t *sem),int sem_trywait(sem_t *sem)
    29 参数:sem为信号灯指针
    30 返回值:成功时,返回0,失败,-1
    31 
    32 5.sem_getvalue函数
    33 功能:获得信号灯的值
    34 头文件:#include <semaphore.h>
    35 函数原型:int sem_getvalue(sem_t *sem,int *valp)
    36 参数:sem为信号灯指针,valp为信号灯的值
    37 返回值:成功时,返回0,失败,-1
    38 
    39 6.sem_post函数
    40 功能:使用完共享资源后,信号灯值加1,唤醒其他睡眠的。
    41 头文件:#include <semaphore.h>
    42 函数原型:int sem_post(sem_t *sem)
    43 参数:sem为信号灯指针
    44 返回值:成功时,返回0,失败,-1

    示例代码:

     1 /*semopen_pth.c*/
     2 #include <stdio.h>
     3 #include <semaphore.h>
     4 #include <fcntl.h>
     5 #include <pthread.h>
     6                                                                                
     7 void print();
     8 void * thread_function(void *arg);
     9 sem_t * sem;
    10                                                                                
    11 int main(int argc,char * argv[])
    12 {
    13         int n=0;
    14         pthread_t tid;
    15         if(argc != 2)
    16         {
    17                 printf("Usage:%s name.\n",argv[0]);
    18                 exit(0);
    19         }
    20         //init semaphore
    21         sem=sem_open(argv[1],O_CREAT,0644,3);
    22         while(n++<5)
    23         {
    24                 if((pthread_create(&tid,NULL,thread_function,NULL))!=0)
    25                 {
    26                         printf("can't create pthread.\n");
    27                         exit(0);
    28                 }
    29         }
    30         pthread_join(tid,NULL); //主线程需要等会其它线程
    31         sem_close(sem);
    32         sem_unlink(argv[1]);
    33         return 0;
    34 }
    35                                                                                
    36 void * thread_function(void *arg)
    37 {
    38         sem_wait(sem);
    39         print();
    40         sleep(1); //因为共享段执行过快,不能达到同步效果,所以需要睡眠
    41         sem_post(sem);
    42         printf("finish, pthread_id is %d\n",pthread_self());
    43 }
    44                                                                                
    45 void print()
    46 { 
    47         int value;
    48         printf("pthread_id is %d, get the resource\n",pthread_self());
    49         sem_getvalue(sem,&value);
    50         printf("now,the semaphore value is %d\n",value);
    51 }

    编译并执行:

     1 root@linux:/mnt/hgfs/C_libary# gcc -lpthread -o semopen_pth semopen_pth.c
     2 semopen_pth.c: In function ‘main’:
     3 semopen_pth.c:17: warning: incompatible implicit declaration of built-in function ‘exit’
     4 semopen_pth.c:26: warning: incompatible implicit declaration of built-in function ‘exit’
     5 semopen_pth.c: In function ‘thread_function’:
     6 semopen_pth.c:41: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’
     7 semopen_pth.c: In function ‘print’:
     8 semopen_pth.c:47: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’
     9 root@linux:/mnt/hgfs/C_libary# 
    10 注:产生了一些警告,先不管这些,看看是否能运行
    11 root@linux:/mnt/hgfs/C_libary# ./semopen_pth sem
    12 pthread_id is -1217336464, get the resource
    13 now,the semaphore value is 2
    14 pthread_id is -1225729168, get the resource
    15 now,the semaphore value is 1
    16 pthread_id is -1234121872, get the resource
    17 now,the semaphore value is 0
    18 finish, pthread_id is -1217336464
    19 finish, pthread_id is -1225729168
    20 finish, pthread_id is -1234121872
    21 pthread_id is -1242514576, get the resource
    22 now,the semaphore value is 2
    23 pthread_id is -1250907280, get the resource
    24 now,the semaphore value is 1
    25 finish, pthread_id is -1242514576
    26 finish, pthread_id is -1250907280
    27 root@linux:/mnt/hgfs/C_libary# 

    有名信号灯同步多进程:

      unix网络编程第二卷,如是说不同进程(不管是否彼此有无亲缘关系),他们都可以访问同一个信号灯,只是需要在sem_open的时候传入的名字是一样就行。在有亲缘关系时,Posix中的fork如是描述,在父进程中打开的任何信号灯,仍应在子进程中打开。

    示例代码:

     1 /*semopen_pro.c*/
     2 #include <stdio.h>
     3 #include <semaphore.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 #include <sys/types.h>
     7 #include <sys/wait.h>
     8 
     9 void print();
    10 sem_t * sem;                                                                                                    
    11 
    12 int main(int argc,char * argv[])
    13 {
    14         int n=0,j;
    15         pid_t pid;
    16 
    17         if(argc != 2)
    18         {
    19                 printf("Usage:%s name.\n",argv[0]);
    20                 exit(0);
    21         }
    22 
    23         //该信号灯不会因为不同进程而不同。
    24         sem=sem_open(argv[1],O_CREAT,0644,3);
    25         while(n++<5)
    26         {
    27                 pid = fork();
    28                 if(pid == 0)
    29                 {
    30                         sem_wait(sem);
    31                         print();
    32                         sleep(1);
    33                         sem_post(sem);
    34                         printf("finish,the pid is %d\n",getpid());
    35                         exit(0);
    36                 }
    37         }
    38 
    39         j=0;
    40         
    41         //等待所有子进程退出
    42         while(j++<5)
    43            wait(NULL);
    44         sem_close(sem);
    45         sem_unlink(argv[1]);
    46         return 0;
    47 }
    48                                                                                                                                                                                                        
    49 void print()
    50 {
    51         int value;
    52         printf("pid is %d, get the resource\n",getpid());
    53         sem_getvalue(sem,&value);
    54         printf("now,the semaphore value is %d\n",value);
    55 }

    编译并执行:

     1 root@linux:/mnt/hgfs/C_libary# gcc -o semopen_pro semopen_pro.c
     2 semopen_pro.c: In function ‘main’:
     3 semopen_pro.c:19: warning: incompatible implicit declaration of built-in function ‘exit’
     4 semopen_pro.c:34: warning: incompatible implicit declaration of built-in function ‘exit’
     5 /tmp/ccUECdL7.o: In function `main':
     6 semopen_pro.c:(.text+0x5d): undefined reference to `sem_open'
     7 semopen_pro.c:(.text+0x81): undefined reference to `sem_wait'
     8 semopen_pro.c:(.text+0x9f): undefined reference to `sem_post'
     9 semopen_pro.c:(.text+0x107): undefined reference to `sem_close'
    10 semopen_pro.c:(.text+0x117): undefined reference to `sem_unlink'
    11 /tmp/ccUECdL7.o: In function `print':
    12 semopen_pro.c:(.text+0x14e): undefined reference to `sem_getvalue'
    13 collect2: ld returned 1 exit status
    14 注:sem_XXX函数不是标准库函数,链接时需要指定库-lrt or -pthread.
    15 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o semopen_pro semopen_pro.c
    16 semopen_pro.c: In function ‘main’:
    17 semopen_pro.c:19: warning: incompatible implicit declaration of built-in function ‘exit’
    18 semopen_pro.c:34: warning: incompatible implicit declaration of built-in function ‘exit’ 
    19 root@linux:/mnt/hgfs/C_libary# ./semopen_pro sem
    20 pid is 5262, get the resource
    21 now,the semaphore value is 2
    22 pid is 5263, get the resource
    23 now,the semaphore value is 1
    24 pid is 5264, get the resource
    25 now,the semaphore value is 0
    26 finish,the pid is 5262
    27 pid is 5265, get the resource
    28 now,the semaphore value is 0
    29 finish,the pid is 5263
    30 pid is 5266, get the resource
    31 now,the semaphore value is 0
    32 finish,the pid is 5264
    33 finish,the pid is 5265
    34 finish,the pid is 5266
    35 root@linux:/mnt/hgfs/C_libary# 

    基于内存的信号灯同步多线程:

     1 sem_init()
     2 功能:初始化信号灯。
     3 头文件:#include <semaphore.h>
     4 函数原型:int sem_open(sem_t * sem,int shared,unsigned int value);
     5 参数:sem为信号灯指针,shared是指同步多线程还是多进程(0:多线程,其他:多进程),value为信号量值
     6 返回值:成功时,返回0,失败时,返回-1
     7 
     8 sem_destroy()
     9 功能:关闭信号
    10 头文件:#include <semaphore.h>
    11 函数原型:int sem_destroy(sem_t * sem)
    12 参数:sem为信号灯的指针
    13 返回值:成功时,返回0,失败,-1

    示例代码:

     1 /*seminit_pth*/
     2 #include <stdio.h>
     3 #include <semaphore.h>
     4 #include <fcntl.h>
     5 #include <pthread.h>
     6                                                                                                     
     7 void print();
     8 void * thread_function(void *arg);
     9 sem_t sem;
    10                                                                                                     
    11 int main(int argc,char * argv[])
    12 {
    13         int n=0;
    14         pthread_t tid;
    15         //init semaphore
    16         sem_init(&sem,0,3);
    17         while(n++<5)
    18         {
    19                 if((pthread_create(&tid,NULL,thread_function,NULL))!=0)
    20                 {
    21                        printf("can't create pthread.\n");
    22                         exit(0);
    23                 }
    24         }
    25         pthread_join(tid,NULL);
    26         sem_destroy(&sem);
    27         return 0;
    28 }
    29                                                                                                     
    30 void * thread_function(void *arg)
    31 {
    32         sem_wait(&sem);
    33         print();
    34         sleep(1); //
    35         sem_post(&sem);
    36         printf("finish, pthread_id is %d\n",pthread_self());
    37 }
    38                                                                                                    
    39 void print()
    40 {
    41         int value;
    42         printf("pthread_id is %d, get the resource\n",pthread_self());
    43         sem_getvalue(&sem,&value);
    44         printf("now,the semaphore value is %d\n",value);
    45 }

    编译运行:

     1 root@linux:/mnt/hgfs/C_libary# gcc -lrt -o seminit_pth seminit_pth.c
     2 seminit_pth.c: In function ‘main’:
     3 seminit_pth.c:21: warning: incompatible implicit declaration of built-in function ‘exit’
     4 seminit_pth.c: In function ‘thread_function’:
     5 seminit_pth.c:35: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’
     6 seminit_pth.c: In function ‘print’:
     7 seminit_pth.c:41: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’
     8 root@linux:/mnt/hgfs/C_libary# 
     9 root@linux:/mnt/hgfs/C_libary# ./seminit_pth
    10 pthread_id is -1224959120, get the resource
    11 now,the semaphore value is 2
    12 pthread_id is -1233351824, get the resource
    13 now,the semaphore value is 1
    14 pthread_id is -1241744528, get the resource
    15 now,the semaphore value is 0
    16 finish, pthread_id is -1224959120
    17 finish, pthread_id is -1233351824
    18 finish, pthread_id is -1241744528
    19 pthread_id is -1250137232, get the resource
    20 now,the semaphore value is 2
    21 pthread_id is -1216566416, get the resource
    22 now,the semaphore value is 1
    23 finish, pthread_id is -1250137232
    24 finish, pthread_id is -1216566416
    25 root@linux:/mnt/hgfs/C_libary# 
  • 相关阅读:
    SpringBoot学习:整合shiro(验证码功能和登录次数限制功能)
    SpringBoot学习:整合shiro(rememberMe记住我功能)
    SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
    SpringBoot学习:整合Redis
    SpringBoot学习:获取yml和properties配置文件的内容
    SpringBoot学习:使用spring-boot-devtools进行热部署
    SpringBoot学习:添加JSP支持
    SpringBoot学习:整合MyBatis,使用Druid连接池
    DL杂谈
    YOLO3训练widerface数据集
  • 原文地址:https://www.cnblogs.com/polestar/p/2455519.html
Copyright © 2011-2022 走看看