linux信号量POSIX,linux进程间通信之Posix 信号量用法详解代码举例

Posix信号量不同于System V信号量的信号量集,Posix信号量是单一的信号量,分为有名信号量和无名信号量。

Posix有名信号量是使用Posix IPC名字标示的信号量,可用于进程和线程间的同步;Posix无名信号量是指基于内存的信号量,存放在共享内存区中,用于进程与线程间的同步。

Posix有名信号量可以是内核维护,也可以在文件系统中维护,这取决于信号量对应的路径名是否映射到了真正的磁盘文件上,如果有映射到则在文件系统中维护,否则在内核中维护,Posix有名信号量由函数sem_open(),sem_close(),sem_unlink(),sem_wait(),sem_trywait(),sem_post(),sem_getvalue()来操作使用。

Posix无名信号量根据sem_init()函数调用时的输入参数不同而分为进程间共享和线程间共享,函数原型int sem_init(sem_t *sem,int shared,unsigned int value); 的第二个参数shared若为0,则表示是线程间共享;若shared是1,则表示是进程间共享,同时第一个参数变量sem_t数据类型变量sem必须驻留在所有希望共享它的进程所共享的内存区中。Posix无名信号量由函数sem_init(),sem_destroy(),sem_wait(),sem_trywait(),sem_post(),sem_getvalue()来操作使用。

Posix信号量相关函数的原型及头文件:

#include

sem_t *sem_open(const char*name,int oflag,.../*mode_t mode, unsigned int value*/);

功能:创建一个新的有名信号量或打开一个已存在的有名信号量

返回值:若成功返回指向信号量的指针,该指针用作sem_close(),sem_wait(),sem_trywait(),sem_post,sem_getvalue()的参数;若出错返回SEM_FAILED.

参数:name为路径名;oflag可以是0,O_CREAT或O_CREAT|O_EXCL;mode参数可选是指定权限位,在O_CREAT是有效;value参数可选是指定信号量的初始值,不能超过SEM_VALUE_MAX,二值信号量的初始值通常为1,计数信号量初始值通常大于1。

int sem_close(sem_t *sem);

功能:关闭由sem_open()打开的有名信号量。

返回值:若成功返回0,若失败返回-1

int sem_unlink(const char *name);

功能:从系统中真正删除信号量

返回值:若成功返回0,若失败返回-1

int sem_wait(sem_t *sem);

功能:测试指定信号量的值,如果值大于0,则减1并立即返回;如果值等于0,则调用的进程或线程阻塞进入睡眠,直到该值变为大于0,此时会再减1,函数随后返回。这种“测试病减1”的操作必须是原子的。

返回值:成功返回0,出错返回-1

int sem_trywait(sem_t *sem);

功能:与sem_wait()相同,只是当所测试的指定信号量是0时,并不阻塞进入睡眠,而是返回一个EAGAIN错误。

返回值:成功返回0,出错返回-1

int sem_post(sem_t *sem);

功能:把所指定的信号量值加1,然后唤醒正在等待该信号量值变为正数的任意进程或线程。

返回值:成功返回0,出错返回-1

int sem_getvalue(sem_t *sem, int *valp);

功能:获取指定信号量的当前值存入valp指针中,如果信号量已上锁,则获取值为0或某个负数,绝对值是等待该信号量解锁的线程数。

返回值:成功返回0,出错返回-1.

int sem_int(sem_t *sem, int shared, unsigned int value);

功能:初始化Posix共享内存的无名信号量。

返回值: 出错返回-1.

参数:sem是信号量的指针;shared为0是线程共享,为1是进程共享(sem需驻留共享内存);value是初始化值。

int sem_destory(sem_t *sem);

功能:摧毁sem_init()初始化的无名信号量。

返回值:成功返回0,出错返回-1

代码举例,父子进程采用二值信号量sem_test.c:

#include

#include

#include

#include

#include

#include

#define USE_POSIX_SEM 1

#define MYSEM "/mysem"

#define RUN_TIMES 5

int main(void)

{

#if USE_POSIX_SEM

sem_t *semId;

int val;

//sem_unlink(MYSEM);

semId=sem_open(MYSEM,O_CREAT,0666,0);

if(SEM_FAILED==semId)

{

printf("sem open failed!\n");

return 0;

}

sem_getvalue(semId,&val);

printf("sem_val init=%d\n",val);

sem_post(semId);

sem_getvalue(semId,&val);

printf("sem_val after post=%d\n",val);

#endif

int pid=fork();

if (0==pid)

{

int i;

#if USE_POSIX_SEM

sem_wait(semId);

#endif

for(i=0;i

{

printf("child running!\n");

sleep(1);

}

#if USE_POSIX_SEM

sem_post(semId);

#endif

printf("child end\n");

exit(0);

}

else if (pid>0)

{

int i;

#if USE_POSIX_SEM

sem_wait(semId);

#endif

for(i=0;i

{

printf("parent running!\n");

sleep(1);

}

#if USE_POSIX_SEM

sem_post(semId);

#endif

printf("parent end\n");

}

waitpid(pid,NULL,0);

printf("progam finished\n");

#if USE_POSIX_SEM

sem_close(semId);

sem_unlink(MYSEM);

#endif

return 0;

} 复制代码

运行结果:

$ ./a.out

sem_val init=0

sem_val after post=1

parent running!

parent running!

parent running!

parent running!

parent running!

parent end

child running!

child running!

child running!

child running!

child running!

child end

progam finished

可以看出,父进程先执行,执行5次打印后post 信号量后,子进程才执行。

如果关闭Posix 信号量,条件编译宏设为“#define USE_POSIX_SEM 0”,运行结果为:

$ ./a.out

parent running!

child running!

parent running!

child running!

parent running!

child running!

parent running!

child running!

child running!

parent running!

parent end

child end

progam finished

可以看到父子进程交替执行,存在竞争关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值