进程通信之无名信号量

简介:

进程通信之无名信号量


    和有名信号量类似,无名信号也是进程之间/线程之间通信的主要手段,唯一不同的是他不能用在不同进程之间。当然如果把无名信号量放在多个进程都可以访问的共享内存里,也可以实现进程之间的通信,但这主要还是借助于共享内存的机制。下面将根据使用无名信号量依赖的头文件、需要链接的库文件、常用的函数分别进行介绍。


依赖头文件:#include <semaphore.h>


链接依赖库: 需要链接到libpthread.so,因此makefile里需要指定-lpthread


重要函数列表:


int sem_init(sem_t *sem, int pshared, unsigned int value);

无名信号量的初始化函数,这个函数体现了无名信号量和有名信号量的主要区别,不同于有名信号量的初始化函数sem_open(),它不需要指定一个文件名,只需要传递一个进程、线程都可以访问的信号量指针进去就可以。如果需要在同一个进程的不同线程之间访问,那么pshared必须设置为0,并且第一参数必须保证每个线程都可以访问;如果需要在不同进程间访问,那么pshared必须设置为1,并且第一个参数必须放在共享内存区域。这个函数的地三个参数value指定了该信号量初始化的值,它代表系统刚开始可用的系统资源的个数。

当上面的函数返回为0时,表示函数调用成功;当返回为-1的时候,代表出错,错误代码放在errno里面,可以通过strerror(errno)打印出来。



int sem_post(sem_t *sem);

unlock无名信号量,并且把可用的资源个数加1,唤醒等待当前信号量的线程或进程,让被唤醒的进程或线程可以拿到锁。函数返回值同上。


int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

上面的三个函数都能查询当前有没有可用资源,如果有:就抢到锁并把当前可用的资源数目减1。如果没有可用资源:不同的是sem_wait()会把当前进程或线程加入到休眠队列,直到被唤醒;而sem_trywait()函数在系统没有可用资源的情况下会立即返回错误,并把错误代码设置为EAGAIN,当前进程或线程不会被阻塞;而sem_timewait()在没有可用资源的情况下,最长会被阻塞abs_timeout的时长,然后返回错误,并把错误代码设置为ETIMEDOUT。


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

得到当前信号量的值(代表当前系统可用资源的数量),并把它放到sval指向的内存里面。



代码示例

#include <stdio.h>

#include <stdint.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>


#include <fcntl.h>           /* For O_* constants */

#include <sys/stat.h>        /* For mode constants */

#include <semaphore.h>

#include <errno.h>


sem_t clnt_sem;

int create_done = 0;


void state_thread1()

{

while(1) {

if (!create_done) continue;

printf("%s: Wait semp....\n", __FUNCTION__);

sem_wait(&clnt_sem);

printf("%s: Wait semp done: semp comes\n",  __FUNCTION__);

}

}


void state_thread2()

{

while(1) {

printf("%s: Wait semp....\n", __FUNCTION__);

sem_wait(&clnt_sem);

printf("%s: Wait semp done: semp comes\n",  __FUNCTION__);

sleep(10);

}

}



void main(void)

{

pthread_t ftids;

int ret;


ret = sem_init(&clnt_sem,0, 3);

if (ret < 0) {

printf("%s\n", strerror(errno));

}


pthread_create(&ftids, NULL, (void *)state_thread1, NULL);

pthread_create(&ftids, NULL, (void *)state_thread2, NULL);

create_done = 1;

sem_post(&clnt_sem);


while(1) {

printf("IN Clnt main process\n");

sleep(10);

}


编译和运行结果:

[xqch@localhost testcases]$ gcc -o sem_nameless sem_nameless.c -lpthread

[xqch@localhost testcases]$ ./sem_nameless

IN Clnt main process

state_thread2: Wait semp....

state_thread2: Wait semp done: semp comes

state_thread1: Wait semp....

state_thread1: Wait semp done: semp comes

state_thread1: Wait semp....

state_thread1: Wait semp done: semp comes

state_thread1: Wait semp....

state_thread1: Wait semp done: semp comes

state_thread1: Wait semp....

IN Clnt main process

state_thread2: Wait semp....



















本文转自存储之厨51CTO博客,原文链接:http://blog.51cto.com/xiamachao/1791534 ,如需转载请自行联系原作者


相关文章
|
1月前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
1月前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
2月前
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
25 0
|
3月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
373 4
|
3月前
|
Linux C语言
C语言 多进程编程(七)信号量
本文档详细介绍了进程间通信中的信号量机制。首先解释了资源竞争、临界资源和临界区的概念,并重点阐述了信号量如何解决这些问题。信号量作为一种协调共享资源访问的机制,包括互斥和同步两方面。文档还详细描述了无名信号量的初始化、等待、释放及销毁等操作,并提供了相应的 C 语言示例代码。此外,还介绍了如何创建信号量集合、初始化信号量以及信号量的操作方法。最后,通过实际示例展示了信号量在进程互斥和同步中的应用,包括如何使用信号量避免资源竞争,并实现了父子进程间的同步输出。附带的 `sem.h` 和 `sem.c` 文件提供了信号量操作的具体实现。
|
4月前
|
消息中间件 Linux 开发者
Linux进程间通信秘籍:管道、消息队列、信号量,一文让你彻底解锁!
【8月更文挑战第25天】本文概述了Linux系统中常用的五种进程间通信(IPC)模式:管道、消息队列、信号量、共享内存与套接字。通过示例代码展示了每种模式的应用场景。了解这些IPC机制及其特点有助于开发者根据具体需求选择合适的通信方式,促进多进程间的高效协作。
184 3
|
4月前
|
Linux
Linux源码阅读笔记13-进程通信组件中
Linux源码阅读笔记13-进程通信组件中
|
4月前
|
消息中间件 安全 Java
Linux源码阅读笔记13-进程通信组件上
Linux源码阅读笔记13-进程通信组件上
|
4月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
74 0
|
4月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器

相关实验场景

更多