进程间的通信---信号量(semget,semctl,semop)

信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量就是一个计数器。

当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用。当一个进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作为原子操作,这是由于信号量主要的作用是维护资源的互斥或多进程的同步访问。而信号量的创建以及初始化上,不能保证操作为原子操作。

使用信号量的原因:为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,它可以通过生成并使用令牌来授权,在任意时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来协调进程对共享资源的访问的。

信号量的工作原理:

由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv)

P(sv):如果sv的值大于0,就减1,如果它的值为0,就挂起该进程的执行

V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就+1

几个函数:

  1. 创建一个信号量集对象(得到一个信号量集标识符)

    int semget(key_t key,int nsems,int semflg)

    key:由ftok()函数的得到

    nsems:创建信号量集中信号的个数

    semflg:

IPC_CREAT:若内核中不存在键值与key相等的信号量集,则创建,否则,返回此信号量集的标识符

IPC_EXCL:单独使用无意义

IPC_CREAT | IPC_EXCL :创建一个新的信号量集并返回信号量集的标识符,否则,返回-1.

返回值:成功返回信号量集的标识符。失败返回-1.

2. 完成对信号量的P,V操作

int semop(int semid,struct sembuf* sops,unsigned nsops)

返回值:成功时,返回信号量集的标识符。否则,返回-1.

semid:信号量集标识符

nsops:进行操作信号量的个数,即sops结构变量的个数,需大于或等于1.

sops:指向进行操作的信号量集结构体数组的首地址

struct sembuf

{

short semnum;//信号量集合中的信号量编号,0代表第一个信号量

short val;//val>0 进行V操作信号量值+val,表示进程释放控制的资源

short flag; //设置信号量的默认操作  IPC_NOWAIT 设置信号量操作不等待

//SEM_UNDO 选项会让内核记录一个与调用进程相关的UNDO记录,如果该进                             程崩溃,则根据这个进程的UNDO记录自动恢复相应的信号量的计数

}

     当操作信号量(semop)时,flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。
  如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。

3.在指定的信号集或信号集内的某个信号上执行操作控制

函数原型:int semctl(int semid,int semnum,int cmd,union semun arg)

semid: 信号量集标识符

semnum:信号量集数组上的下标,表示某一个信号量

arg:

union semun {

short val;          /*SETVAL用的值*/

struct semid_ds* buf; /*IPC_STAT、IPC_SET用的semid_ds结构*/

unsigned short* array; /*SETALL、GETALL用的数组值*/

struct seminfo *buf;   /*为控制IPC_INFO提供的缓存*/

} arg;

“comm.h”

“comm.c”

“test.c”

测试结果:

时间: 2024-10-13 00:45:57

进程间的通信---信号量(semget,semctl,semop)的相关文章

Linux进程间通信 -- 信号量 semget()、semop()、semctl()

这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面就进入信号量的讲解. 一.什么是信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问代码的临界区域.临界区域是指执行数据更新的代码需要独占式地执行.而信号量就可以提供这样的一种访问机制,让一个临界区同

Nginx之进程间的通信机制(信号、信号量、文件锁)

1. 信号 Nginx 在管理 master 进程和 worker 进程时大量使用了信号.Linux 定义的前 31 个信号是最常用的,Nginx 则通过重定义其中一些信号的处理方法来使用吸纳后,如接收到 SIGUSR1 信号就意味着需要重新打开文件. 使用信号时 Nginx 定义了一个 ngx_signal_t 结构体用于描述接收到的信号时的行为: typedef struct { // 需要处理的信号 int signo; // 信号对应的字符串名称 char *signame; // 这个

linux 进程间的通信

现在linux使用的进程间通信方式:(1)管道(pipe)和有名管道(FIFO)(2)信号(signal)(3)消息队列(4)共享内存(5)信号量(6)套接字(socket) 为何进行进程间的通信:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到.C.通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程).D.资源共享

Linux进程间的通信

一.管道 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: A. 管道是半双工的,数据只能向一个方向流动: B. 需要双工通信时,需要建立起两个管道: C. 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): D. 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中. 匿名管道的创建:该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义;因此,一

Linux/UNIX之进程间的通信(2)

进程间的通信(2) 有三种IPC我们称为XSI IPC,即消息队列.信号量以及共享存储器,它们之间有很多相似之处. 标识符和键 每个内核的IPC结构(消息队列.信号量或共享存储段)都用一个非负整数的标识符加以引用.例如,为了对一个消息队列发送或取消息,只需要知道其队列标识符.与文件描述符不同,IPC标识符不是小的整数.当一个IPC结构被创建,以后被删除时,与这种结果相关的标识符连续加1,知道达到一个整型数的最大值,然后又回到0. 标识符是IPC对象的内部名.为使多个合作进程能够在同一IPC对象上

Linux进程间的通信方法

linux进程间的通信方法总结如下 通过fork函数把打开文件的描述符传递给子进程 通过wait得到子进程的终结信息 通过加锁的方式,实现几个进行共享读写某个文件 进行间通过信号通信,SIGUSR1和SIGUSR2实现用户定义功能 利用pipe进行通信 FIFO文件进行通信 mmap,几个进程映射到同一内存区 SYS IPC 消息队列,信号量(很少用) UNIX Domain Socket,常用

Linux/UNIX进程间的通信(1)

进程间的通信(1) 进程间的通信IPC(InterProcessCommunication )主要有以下不同形式: 半双工管道和FIFO:全双工管道和命名全双工管道:消息队列,信号量和共享存储:套接字和STREAMS 管道 pipe函数 当从一个进程连接到另一个进程时,我们使用术语管道.我们通常是把一个进程的输出通过管道连接到另一个进程的输入. 管道是由调用pipe函数创建的: #include<unistd.h> int pipe(intpipefd[2]); 经由参数pipefd返回两个文

Nginx学习——Nginx进程间的通信

nginx进程间的通信 进程间消息传递 共享内存 共享内存还是Linux下提供的最主要的进程间通信方式,它通过mmap和shmget系统调用在内存中创建了一块连续的线性地址空间,而通过munmap或者shmdt系统调用可以释放这块内存.使用共享内存的优点是当多个进程使用同一块共享内存时,在不论什么一个进程改动了共享内存中的内容后,其它进程通过訪问这段共享内存都可以得到改动后的内容. Nginx定义了ngx_shm_t结构体.用于描写叙述一块共享内存, typedef struct{ //指向共享

Linux进程间的通信方法简介

一.本地进程间的通信方式: 1.管道(pipe) 利用管道文件可以进行进程间数据的通信,通常是具有血缘关系的父子进程间的通信方式. 管道通信为半双工模式,父子进程可以通过调用内核中的read()和write()命令来向管道文件进行读写操作. 管道通信是基于硬盘内的文件,所以I/O速度较低. 2.消息队列 消息队列是一种类似链表的数据结构,存放于内存中,因此I/O速度较管道更快,通过ipcs -q命令可以查看当前系统中被创建的消息队列. 多个不同进程可以使用同一个消息队列进行通信,消息队列中的数据