几种进程间的通信方式

转自:http://www.cnblogs.com/mydomain/archive/2010/09/23/1833369.html

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

 
昨天总结了一些进程之间的通信方式,其实就是给一些函数做了基本的用法记录,今天看了看还是好好的看一下这

几个的区别。

几种方式:

文件、管道、共享内存空间:

1.文件方式的进程通信就是通过读写同一个文件来完成共享数据。一个进程将数据写入文件,另一个进程再将

数据从文件中读出。

客户端能够读取文件,且能够多个客户端同时读取,系统允许同时打开一个文件。

服务器端通过清空重写的方式对文件内容进行修改

问题:不能避免在文件尚未进行完写操作时就有进程读取文件内容,这时会造成读取的文件内容为空或者是读

出文件中的部分数据。

解决方案:可以通过文件锁的方式进行控制。


2.命名管道:常规的管道只能连接相关进程,由进程创建并由最后一个进程关闭。而命名管道可以连接不相关

的进程。它是个FIFO先进先出队列,即使没有进程,命名管道依然可以存在,它不依赖于进程。服务器将字节

写入队列,客户端从队列头部移出字节。服务器必须重写数据。它没有竞争的问题,在没有超过管道最大长度

的时候,read和write都是原子操作,先将管道清空,然后再将管道写满,在读者和写者联通之前系统内核将

进程刮起。

共享内存段:不依赖于进程的存在而存在。共享内存段拥有权限系统来控制进程各自的访问权限。多个客户端

都可以同时从内存中读数据。

问题:如果读取是在服务器向内存中写数据的时候进行的,有可能既读到旧数据又读到新数据。

解决方案:信号量机制。


比较:

1.文件和命名管道消耗操作多。

2.文件和共享内存是无连接的

3.命名管道和共享内存只能在本机中使用

4.使用共享内存和文件要比使用管道麻烦,要处理竞态。


进程的产生:

1.进程号:
getpid()---当前进程id
getppid()---父进程id

2.fork()---复制进程,子进程id与父进程id不同,内存等与父进程不同,其他与父进程共享。

3.system()---当这个函数中的命令执行完毕之后才能继续本进程,也就是说它可以阻塞本进程。

4.exec()函数系列---新进程代替原进程,只有id与原id相同。
 ---普遍用法:使用fork()分岔进程,在新进程中调用exec()函数,这样exec()就占用了原来系统资源来运行(id没换但内容换了,挂得还是羊头卖得却是狗日)

5.init---进程都是有init直接或间接fork()出来的。

进程间的通信:

1.管道:

int pipe(int filedes[2])---创建管道,如进程A、B,则每个进程都有读和写两个描述符,在通信的时候关闭不用的那个。

命名管道 mkfifo

2.消息队列:

ftok()---键值构造函数,下面的函数需要这里的键值

msgget()---创建一个消息队列或者访问一个现有队列。

msgsnd()---向队列传递消息

msgrcv()---接收消息队列中的消息

msgclt()---向内核发送一个cmd命令,内核根据此来判断进行何种操作。


信号量:控制多个进程共享资源的访问。

semget()---新建信号量,返回信号的id

semmlt()---发送命令建立value个初始值的信号量

semop()---向信号量发送命令

semctl()---信号量控制的其他操作

共享内存:通过共享内存区域实现进程之间的通信

shmget()---创建一个新的共享内存段或者访问一个现有的共享内存段,返回段标识符

shmat()---获取共享内存的地址

shmdt()---删除,实际上是断开,断开后shmid_ds的shm_nattch-1,当==0时真正的删除内存段

shmctl()---对共享内存的控制

信号:最为古老的进程之间的通信方式

进程可以屏蔽大多数信号,除了SIGSTOP SIGKILL

signal()---信号获取函数,对此信号挂接用户自己的处理函数

很明显,上面这些很多函数的名字都是有规律可循的,用法也差不多……

好了,明天继续---线程

http://www.cnblogs.com/wanpengcoder/archive/2010/07/16/1778552.html

原文地址:https://www.cnblogs.com/wuyuankun/p/3687392.html