perror(“sem_unlink”); else printf(“success”); exit(0); } 4. 名称:: sem_getvalue 功能: 测试信号灯 头文件: #include 函数原形: int sem_getvalue(sem_t *sem,int *valp); 参数: sem 指向信号灯的指针 返回值: 若成功则返回0,否则返回-1。 sem_getvalue在由valp指向的正数中返回所指定信号灯的当前值。如果该信号灯当前已上锁,那么返回值或为0,或为某个负数,其绝对值就是等待该信号灯解锁的线程数。
/*semgetvalue.c*/ #include #include #include #include #include int main(int argc,char **argv) { sem_t *sem; int val; if(argc!=2) { printf(“please input a file name!\\n”); exit(1); } sem=sem_open(argv[1],0); sem_getvalue(sem,&val); printf(“getvalue:value=%d\\n”,val); exit(0); }
5. 名称:: sem_wait/sem_trywait 功能: 等待共享资源 头文件: #include 函数原形: int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); 参数: sem 指向信号灯的指针 返回值: 若成功则返回0,否则返回-1。 我们可以用sem_wait来申请共享资源,sem_wait函数可以测试所指定信号灯的值,如果该值大于0,那就将它减1并立即返回。我们就可以使用申请来的共享资源了。如果该值等于0,调用线程就被进入睡眠状态,直到该值变为大于0,这时再将它减1,函数随后返回。sem_wait操作必须是原子的。sem_wait和sem_trywait的差别是:当所指定信号灯的值已经是0时,后者并不将调用线程投入睡眠。相反,它返回一个EAGAIN错误。
下面的程序我们先不去运行,稍后再运行。 /*semwait.c*/ #include #include #include #include #include int main(int argc,char **argv) { sem_t *sem; int val; if(argc!=2) { printf(“please input a file name!\\n”); exit(1); } sem=sem_open(argv[1],0); sem_wait(sem); sem_getvalue(sem,&val); printf(“pid %ld has semaphore,value=%d\\n”,(long)getpid(),val); pause(); exit(0); }
6. 名称:: 功能: 头文件: sem_post 挂出共享资源 #include 函数原形: int sem_post(sem_t *sem); int sem_getvalue(sem_t *sem,int *valp); 参数: sem 指向信号灯的指针 返回值: 若成功则返回0,否则返回-1。
当一个线程使用完某个信号灯时,它应该调用sem_post来告诉系统申请的资源已经用完。本函数和sem_wait函数的功能正好相反,它把所指定的信号灯的值加1,然后唤醒正在等待该信号灯值变为正数的任意线程。
下面的程序我们先不去运行,稍后再运行。 /*sempost.c*/ #include #include #include #include #include int main(int argc,char **argv) { sem_t *sem; int val; if(argc!=2) { printf(“please input a file name!\\n”); exit(1); } sem=sem_open(argv[1],0); sem_post(sem); sem_getvalue(sem,&val); printf(“value=%d\\n”, val); exit(0); }
二、关于posix有名信号灯使用的几点注意 我们要注意以下几点:
1.Posix有名信号灯的值是随内核持续的。也就是说,一个进程创建了一个信号灯,这个进程结束后,这个信号灯还存在,并且信号灯的值也不会改变。 下面我们利用上面的几个程序来证明这点 #./semopen test #./semgetvalue test
value=1 信号的值仍然是1
2。当持有某个信号灯锁的进程没有释放它就终止时,内核并不给该信号灯解锁。
#./semopen test #./semwait test&
pid 1834 has semaphore,value=0 #./semgetvalue test
value=0 信号量的值变为0了
三、posix有名信号灯应用于多线程 #include #include #include #include #include void *thread_function(void *arg); /*线程入口函数*/ void print(pid_t); /*共享资源函数*/ sem_t *sem; /*定义Posix有名信号灯*/ int val; /*定义信号灯当前值*/ int main(int argc,char *argv[]) { int n=0; if(argc!=2) { printf(“please input a file name!\\n”); exit(1); } sem=sem_open(argv[1],O_CREAT,0644,3); /*打开一个信号灯*/ while(n++<5) /*循环创建5个子线程,使它们同步运行*/ { if((pthread_create(&a_thread,NULL,thread_function,NULL))!=0) { perror(“Thread creation failed”); exit(1); } } pthread_join(a_thread,NULL); sem_close(bin_sem); sem_unlink(argv[1]); } void *thread_function(void *arg) { sem_wait(sem); /*申请信号灯*/ print(); /*调用共享代码段*/ sleep(1); sem_post(sem); /*释放信号灯*/ printf(“I’m finished,my tid is %d\\n”,pthread_self()); } void print() { printf(“I get it,my tid is %d\\n”,pthread_self()); sem_getvalue(sem,&val); printf(“Now the value have %d\\n”,val); } 程序用循环的方法建立5个线程,然后让它们调用同一个线程处理函数thread_function,在函数里我们利用信号量来限制访问共享资源的线程数。共享资源我们用print函数来代表,在真正编程中它有可以是一个终端设备(如打印机)或是一段有实际意义的代码。
运行结果为:
#gcc –lpthread –o 8_1 8_1.c #./8_1 test
I get it,my tid is 1082330304 Now the value have 2 Iget it,my pid is 1894 Now the value have 1 Iget it,my pid is 1895 Now the value have 0
I’m finished,my pid is 1893 I’m finished,my pid is 1894 I’m finished,my pid is 1895 I get it,my pid is 1896 Now the value have 2 I get it,mypid is 1897 Now the value have 1
I’m finished,my pid is 1896 I’m finished,my pid is 1897
四、posix有名信号灯应用于多进程
下面就是应用Posix有名信号灯的一个小程序。用它来限制访问共享代码的进程数目。
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库linux多线程编程(5)在线全文阅读。