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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值