码迷,mamicode.com
首页 > 系统相关 > 详细

linux Posix 信号量 二

时间:2015-01-05 12:30:55      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

一、Posix信号量

 

1.Posix信号量分为两种:

1.   有名信号量:使用Posix IPC名字标识(有名信号量总是既可用于线程间的同步,又可以用于进程间的同步)

2.   内存信号量:存放在共享内存区中(基于内存的信号量则必须在创建时指定成是否在进程间共享,且在所有进程的共享内存区,具有随进程的持续性)

Posix信号量不必在内核中维护(System V信号量由内核维护),由可能为路径名的名字来标识。

(Posix信号量更常用于进程间同步,互斥锁常用于线程间同步)

 

2.基本操作:

1.   创建(create):指定初始值。

2.   等待(wait):如果值小于等于0则阻塞,否则将其减一,又称P操作。

3.   挂出(post):将信号量的值加1,加后如果值大于0,则唤醒一个阻塞在等待上的线程,又称V操作。

二值信号量可用于互斥,就像互斥锁一样。但互斥锁必须由锁住它的线程解锁,信号量的挂出却不必由执行过等待的同一线程执行。

信号量的wait和post与条件变量的wait和signal类似,区别是:因为永久的改变了信号量的值,信号量的操作总被记住(会影响到后续的操作);条件变量的signal如果没有线程在等待,该信号将丢失(对后续操作没有影响)。

互斥锁是为上锁而优化的,条件变量是为等待优化的,信号量既可以上锁也可以等待,因此开销更大。

3.Posix信号量操作

有名信号量:

内存信号量:

sem_open

sem_init:需要指定是否共享

                                                                 sem_wait:原子的“测试并减1”操作

                                                                 sem_trywait

                                                                 sem_post:同步技巧中唯一能在信号处理函数内安全调用的操作

                                                                 sem_getvalue

sem_close

sem_destroy

sem_unlink

 

即使当前没有进程打开信号量,它的值仍然保持,因此Posix有名信号量至少是随内核持续的。

在父进程中打开的任何信号量,fork后在子进程中仍打开。

 

 

 

关于posix有名信号量使用的几点注意

 

1、有名信号量使用sem_unlink从系统中删除。每个信号量有一个引用计数器记录当前的打开次数,sem_unlink必须等待这个数为0时才能把name所指的信号量从文件系统中删除。也就是要等待最后一个sem_close发生。

 

2、彼此无亲缘关系的进程间需使用信号量时,一般用有名信号量。如果不需要使用关联名字时,可改用内存信号量。

内存信号量需要放在共享内存区中,并由sem_init函数初始化为shared状态才能被不同进程使用,这种情况下它的持续性与共享内存区相同。sem_init总是初始化信号量的值,因此,对于一个给定的信号量,必须小心保证只调用sem_init一次。

 

3、我们可以用sem_wait来申请共享资源,sem_wait函数可以测试所指定信号量的值,如果该值大于0,那就将它减1并立即返回。我们就可以使用申请来的共享资源了。如果该值等于0,调用线程就被进入睡眠状态,直到该值变为大于0,这时再将它减1,函数随后返回。sem_wait操作必须是原子的。sem_wait和sem_trywait的差别是:当所指定信号量的值已经是0时,后者并不将调用线程投入睡眠。相反,它返回一个EAGAIN错误。

 当一个线程使用完某个信号量时,它应该调用sem_post来告诉系统申请的资源已经用完。本函数和sem_wait函数的功能正好相反,它把所指定的信号量的值加1,然后唤醒正在等待该信号量值变为正数的任意线程。

 

4、.Posix有名信号量的值是随内核持续的。也就是说,一个进程创建了一个信号量,这个进程结束后,这个信号量还存在,并且信号量的值也不会改变。

 

5、当持有某个信号量锁的进程没有释放它就终止时,内核并不给该信号量解锁。

 

 

posix有名信号量应用于多线程

#include <semaphore.h>

#include <unistd.h>

#include <stdio.h>

#include <fcntl.h>

#include <thread.h>

 

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函数来代表,在真正编程中它有可以是一个终端设备(如打印机)或是一段有实际意义的代码。

linux Posix 信号量 二

标签:

原文地址:http://www.cnblogs.com/jiangzhaowei/p/4203047.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!