linux 进程间的通信

现在linux使用的进程间通信方式:
(1)管道(pipe)和有名管道(FIFO)
(2)信号(signal)
(3)消息队列
(4)共享内存
(5)信号量
(6)套接字(socket)

为何进行进程间的通信:
A、数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间
B、共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。
C、通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
D、资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。
E、进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

一、信号量

常见的信号类型

参考:http://blog.csdn.net/ljianhui/article/details/10128731

对信号量的理解:

信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。当一个线程调用Wait操作时,它要么得到资源然后将信号量减一(P操作),要么一直等下去(指放入阻塞队列),直到信号量大于等于一时。Release(释放)实际上是在信号量上执行加操作(V操作),对应于车辆离开停车场,该操作之所以叫做“释放”是因为释放了由信号量守护的资源


对信号量有4种操作(include<semaphore>):

  1. 初始化(initialize),也叫做建立(create)

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

  2. 等信号(wait),也可叫做挂起(suspend)

      int sem_wait(sem_t *sem);

  3. 给信号(signal)或发信号(post)

      int sem_post(sem_t *sem);

  4.清理(destroy)

       int sem_destory(sem_t *sem);

编程步骤:

  创建信号量或获得在系统已存在的信号量

    调用semget()函数

    不同进程使用同一个信号量键值来获得同一个信号量

  初始化信号量

    使用semctl()函数的SETVAL操作

    当使用二维信号量时,通常将信号量初始化为1

  进行信号量的PV操作

    调用semop()函数

    实现进程之间的同步和互斥的核心部分

  如果不需要信号量,则从系统中删除它

    使用semctl()函数的IPC_RMID操作

    在程序中不应该出现对已被删除的信号量的操作

常用函数的说明




二、共享内存

共享内存的接口函数:

# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/shm.h>

key_t  ftok(const char *pathname, int proj_id);

函数用于生成一个键值:key_t key,该键值将作为共享内存对象的唯一性标识符,并提供给为shmget函数作为其输入参数;ftok 函数的输入参数包括一个文件(或目录)路径名:pathname,以及一个额外的数字:proj_id,其中pathname所指定的文件(或目录)要求必须已经存在,且proj_id不可为0in shmget(key_t key, int size, int shmflg);

函数用于创建(或者获取)一个由key键值指定的共享内存对象,返回该对象的系统标识符:shmid

第一个参数,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.

不相关的进程可 以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用shmget函数并提供一 个键,再由系统生成一个相应的共享内存标识符(shmget函数的返回值),只有shmget函数才直接使用信号量键,所有其他的信号量函数使用由 semget函数返回的信号量标识符。

第二个参数,size以字节为单位指定需要共享的内存容量

第三个参数,shmflg 是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享 内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其 他用户创建的进程只能读取共享内存。


void*  shmat(int shmid, const void *shmaddr, int shmflg);

函数用于建立调用进程与由标识符shmid指定的共享内存对象之间的连接;

第一个参数,shm_id是由shmget函数返回的共享内存标识。

第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。

第三个参数,shm_flg是一组标志位,通常为0。

调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1


int   shmdt(void *shmaddr);

函数用于断开调用进程与共享内存对象之间的连接;数用于断开调用进程与共享内存对象之间的连接;

int   shmctl(int shmid, int cmd, struct shmid_ds *buf);

函数用于对已创建的共享内存对象进行查询、设值、删除等操作;

第一个参数,shm_id是shmget函数返回的共享内存标识符。

第二个参数,command是要采取的操作,它可以取下面的三个值 :

    IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。

    IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

    IPC_RMID:删除共享内存段

第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。

struct shmid_ds  

{  

    uid_t shm_perm.uid;  

    uid_t shm_perm.gid;  

    mode_t shm_perm.mode;  

}; 




本文出自 “从零开始” 博客,请务必保留此出处http://9433707.blog.51cto.com/9423707/1559743

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。