标签:附加 exp 删除 div main 错误 共享资源 ini 总结
信号灯用来实现同步——用于多线程,多进程之间同步共享资源(临界资源)。信号灯分两种,一种是有名信号灯,一种是基于内存的信号灯。
有名信号灯,是根据外部名字标识,通常指代文件系统中的某个文件。
基于内存的信号灯,它主要是把信号灯放入内存的,基于内存的信号灯,同步多线程时,可以放到该多线程所属进程空间里;如果是同步多进程,那就需要把信号灯放入到共享内存中(方便多个进程访问)。
有名信号灯和基于内存的信号灯,具体区别体现在创建和销毁两个函数。有名信号灯使用sem_open和sem_close函数。基于内存的信号灯使用sem_init和sem_destroy函数。sem_init的参数可以控制是同步多线程,还是多进程;且该函数只能调用1次,因为调用后信号灯就存在了( 内存指针存在)。一般,使用基于内存的信号灯同步同进程多线程,使用有名信号灯同步多进程。
1.sem_open函数。 功能:创建并初始化信号灯,如果存在就返回存在的信号灯。 头文件:#include <semaphore.h> 函数原型:sem_t * sem_open(const char * name,int oflag,mode_t mode,unsigned int value); 或者:sem_t * sem_open(const char * name,int oflag); 参数:name是给信号灯指定一个名字。oflag的值为O_CREAT,表示如果信号灯不存在,创建信号灯;为O_CREAT|O_EXCL,如果信号灯不存在报错。后面两个参数,只有新建信号灯时使用。mode为信号灯的权限(0644),value为信号灯的值。 返回值:成功时,返回信号灯的指针,错误返回SEM_FAILED 2.sem_close函数。 功能:关闭引用信号灯,信号灯引用计数减1。 头文件:#include <semaphore.h> 函数原型:int sem_close(sem_t * sem) 参数:sem为信号灯的指针 返回值:成功时,返回0,失败,-1 注:每个信号灯有一个引用计数器记录当前打开次数.关闭一个信号灯并没有将它从系统中删除,而是信号灯引用计数减1 3.sem_unlink函数 功能:信号灯引用计数为0时,从系统中删除信号灯。 头文件:#include <semaphore.h> 函数原型:int sem_close(const char *name) 参数:name为信号灯的外部名字 返回值:成功时,返回0,失败,-1 4.sem_wait/sem_trywait函数 功能:等待共享资源,信号灯值为0就睡眠,信号灯值大于0,就使用共享资源,信号灯值减1。sem_trywait当信号灯值为0时,不睡眠,报错。 头文件:#include <semaphore.h> 函数原型:int sem_wait(sem_t *sem),int sem_trywait(sem_t *sem) 参数:sem为信号灯指针 返回值:成功时,返回0,失败,-1 5.sem_getvalue函数 功能:获得信号灯的值 头文件:#include <semaphore.h> 函数原型:int sem_getvalue(sem_t *sem,int *valp) 参数:sem为信号灯指针,valp为信号灯的值 返回值:成功时,返回0,失败,-1 6.sem_post函数 功能:使用完共享资源后,信号灯值加1,唤醒其他睡眠的。 头文件:#include <semaphore.h> 函数原型:int sem_post(sem_t *sem) 参数:sem为信号灯指针 返回值:成功时,返回0,失败,-1
总结:
sem_wait在一个信号灯上等待(以锁住一个资源或等待一个时间),如果信号灯计数比0大,sem_wait函数将计数器减一并马上返回,否则,线程阻塞,一个阻塞的线程通过sem_post来发布一个信号灯(开锁一个资源或等待一个线程),
如果一个以上的线程在信号灯上等待,sem_post将唤醒其中一个(优先级最高的或最早等待的线程),如果没有线程在等待,信号灯计数器被加一。
假如有个代码段,期望最多有两个线程同时在里面执行(其他线程必须等待),可以使用一个信号灯而不需要附加任何状态,初始化信号灯值为2,然后再代码段开始调用sem_wait,结尾处调用sem_post,然后两个线程可以再信号登上等待而不被阻塞,
但是第三个线程将发现信号灯计数器为0,并且阻塞,每个系那成退出代码区时,他信号灯释放一个等待吸纳城(如果有的话恢复计数器)。
unix网络编程第二卷,如是说不同进程(不管是否彼此有无亲缘关系),他们都可以访问同一个信号灯,只是需要在sem_open的时候传入的名字是一样就行。在有亲缘关系时,Posix中的fork如是描述,在父进程中打开的任何信号灯,仍应在子进程中打开。
示例代码:
/*semopen_pro.c*/ #include <stdio.h> #include <semaphore.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> void print(); sem_t * sem; int main(int argc,char * argv[]) { int n=0,j; pid_t pid; if(argc != 2) { printf("Usage:%s name.\n",argv[0]); exit(0); } //该信号灯不会因为不同进程而不同。 sem=sem_open(argv[1],O_CREAT,0644,3); while(n++<5) { pid = fork(); if(pid == 0) { sem_wait(sem); print(); sleep(1); sem_post(sem); printf("finish,the pid is %d\n",getpid()); exit(0); } } j=0; //等待所有子进程退出 while(j++<5) wait(NULL); sem_close(sem); sem_unlink(argv[1]); return 0; } void print() { int value; printf("pid is %d, get the resource\n",getpid()); sem_getvalue(sem,&value); printf("now,the semaphore value is %d\n",value); }
root@linux:/mnt/hgfs/C_libary# gcc -o semopen_pro semopen_pro.c semopen_pro.c: In function ‘main’: semopen_pro.c:19: warning: incompatible implicit declaration of built-in function ‘exit’ semopen_pro.c:34: warning: incompatible implicit declaration of built-in function ‘exit’ /tmp/ccUECdL7.o: In function `main‘: semopen_pro.c:(.text+0x5d): undefined reference to `sem_open‘ semopen_pro.c:(.text+0x81): undefined reference to `sem_wait‘ semopen_pro.c:(.text+0x9f): undefined reference to `sem_post‘ semopen_pro.c:(.text+0x107): undefined reference to `sem_close‘ semopen_pro.c:(.text+0x117): undefined reference to `sem_unlink‘ /tmp/ccUECdL7.o: In function `print‘: semopen_pro.c:(.text+0x14e): undefined reference to `sem_getvalue‘ collect2: ld returned 1 exit status 注:sem_XXX函数不是标准库函数,链接时需要指定库-lrt or -pthread. root@linux:/mnt/hgfs/C_libary# gcc -lrt -o semopen_pro semopen_pro.c semopen_pro.c: In function ‘main’: semopen_pro.c:19: warning: incompatible implicit declaration of built-in function ‘exit’ semopen_pro.c:34: warning: incompatible implicit declaration of built-in function ‘exit’ root@linux:/mnt/hgfs/C_libary# ./semopen_pro sem pid is 5262, get the resource now,the semaphore value is 2 pid is 5263, get the resource now,the semaphore value is 1 pid is 5264, get the resource now,the semaphore value is 0 finish,the pid is 5262 pid is 5265, get the resource now,the semaphore value is 0 finish,the pid is 5263 pid is 5266, get the resource now,the semaphore value is 0 finish,the pid is 5264 finish,the pid is 5265 finish,the pid is 5266 root@linux:/mnt/hgfs/C_libary#
sem_init() 功能:初始化信号灯。 头文件:#include <semaphore.h> 函数原型:int sem_open(sem_t * sem,int shared,unsigned int value); 参数:sem为信号灯指针,shared是指同步多线程还是多进程(0:多线程,其他:多进程),value为信号量值 返回值:成功时,返回0,失败时,返回-1 sem_destroy() 功能:关闭信号 头文件:#include <semaphore.h> 函数原型:int sem_destroy(sem_t * sem) 参数:sem为信号灯的指针 返回值:成功时,返回0,失败,-1
/*seminit_pth*/ #include <stdio.h> #include <semaphore.h> #include <fcntl.h> #include <pthread.h> void print(); void * thread_function(void *arg); sem_t sem; int main(int argc,char * argv[]) { int n=0; pthread_t tid; //init semaphore sem_init(&sem,0,3); while(n++<5) { if((pthread_create(&tid,NULL,thread_function,NULL))!=0) { printf("can‘t create pthread.\n"); exit(0); } } pthread_join(tid,NULL); sem_destroy(&sem); return 0; } void * thread_function(void *arg) { sem_wait(&sem); print(); sleep(1); // sem_post(&sem); printf("finish, pthread_id is %d\n",pthread_self()); } void print() { int value; printf("pthread_id is %d, get the resource\n",pthread_self()); sem_getvalue(&sem,&value); printf("now,the semaphore value is %d\n",value); }
root@linux:/mnt/hgfs/C_libary# gcc -lrt -o seminit_pth seminit_pth.c seminit_pth.c: In function ‘main’: seminit_pth.c:21: warning: incompatible implicit declaration of built-in function ‘exit’ seminit_pth.c: In function ‘thread_function’: seminit_pth.c:35: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’ seminit_pth.c: In function ‘print’: seminit_pth.c:41: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘pthread_t’ root@linux:/mnt/hgfs/C_libary# root@linux:/mnt/hgfs/C_libary# ./seminit_pth pthread_id is -1224959120, get the resource now,the semaphore value is 2 pthread_id is -1233351824, get the resource now,the semaphore value is 1 pthread_id is -1241744528, get the resource now,the semaphore value is 0 finish, pthread_id is -1224959120 finish, pthread_id is -1233351824 finish, pthread_id is -1241744528 pthread_id is -1250137232, get the resource now,the semaphore value is 2 pthread_id is -1216566416, get the resource now,the semaphore value is 1 finish, pthread_id is -1250137232 finish, pthread_id is -1216566416 root@linux:/mnt/hgfs/C_libary#
标签:附加 exp 删除 div main 错误 共享资源 ini 总结
原文地址:https://www.cnblogs.com/tianzeng/p/9314463.html