http://www.ibm.com/developerworks/cn/linux/l-ipc/
https://www.ibm.com/developerworks/cn/linux/l-ipc/part1/
http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html
http://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index2.html
linux至少支持如下IPC机制:(同时支持posix和system V方式)
- 管道,popen(协同进程),FIFO
- System V的信号量,消息队列,共享内存---------- 随内核的; 产生键值的时候,path参数必须引用一个现存的文件。不支持ls,rm,chmod,select,poll等!!!消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- Posix的。。。 ------- 随内核或文件。
- 快速用户空间互斥体
- unix domain socket ----- 随进程
- 共享内存 --- 最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
- signal :kill, raise, alarm, abort和setitimer以及sigqueue函数
- 注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值位于SIGRTMIN及SIGRTMAX之间);不可靠信号是信号值小于SIGRTMIN的信号。信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。
- HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS RTMIN RTMIN+1 RTMIN+2 RTMIN+3 RTMAX-3 RTMAX-2 RTMAX-1 RTMAX
- streams IPC机制,linux本身不支持,有一个单独的安装包;可以跨PC的进程通信;
- 互斥锁或条件变量:动态初始化(不能使静态分配),在共享内存中,它们还可以用于进程间的同步;
- 读写锁:非标准
1. 管道: ----------- 持续性随进程;linux只支持半双工模式;参考源码:openssh, scp.c中do_cmd函数。
- 流模式,无边界(类似tcp);
- 不能随机访问(如lseek),必须顺序访问;
- 如果所有的write端都close,则读端读完所有数据后,将检测到EOF;
- 要求读端所在的进程启动时就close掉write socket,否则读端读不到EOF;
- 如果所有的read端都close,write则会导致SIGPIPE信号,默认kill进程;如果处理货忽略此信号,则返回EPIPE错误;
- 要求写端所在的进程启动时就close掉read socket,否则写端一直可以写直到buffer写满;
- 有些unix实现的pipe是全双工的,称之为stream pipes。---非标准,最好不要依赖这个语法。如果需要,可以使用unix domain socket pairs(socketpair函数创建);
- 小于等于PIPE_BUF的数据可以一次传输完毕,即原子操作;(fpathconf(fd, _PC_PIPE_BUF));
- 系统有最大缓存能力,一般不需要考虑,读端尽快处理即可。最小page size,最大/proc/sys/fs/pipe-max-size,可以通过fcntl(fd, F_SETPIPE_SZ, size)设置此值;fcntl(fd, F_GETPIPE_SZ)读取此值;
- 一般使用read、write操作;
- 也可以使用fdopen获取文件指针FILE *,通过stdio函数使用,如printf(), scanf()等;
- 从2.6.27开始,支持非标准pipe2,其提供两个flag:O_CLOEXEC和O_NONBLOCK;
- O_NONBLOCK还可以通过fcntl实现;
- 分配文件描述符从小到大找空闲的文件描述符;
2. FIFO:
- 持续性随进程,不过最后一个引用的进程终止时,数据删除,名字保留,直到显示删除。
- mkfifo
- 阻塞方式打开,两个进程对FIFO的打开顺序要求交叉,否则容易引起死锁;
- 非阻塞方式打开,如果是只写的FIFO,必须先有读打开,否则返回ENXIO错误;
- PIPE_BUF大小内的写操作为原子操作;
- OPEN_MAX为一个进程在任意时刻打开的最大描述符数;
- 。。。
3.消息队列:
缺点:
- 因为不是文件描述符,不支持select和poll。
- 不知道消息的来源,需要在消息内部携带信息表明。
1)system V: msgget
返回任意指定优先级的消息;
不支持mq_notify机制;
2)Posix(相比system V,优选Posix): mq_open,mq_unlink,mq_close, mq_timedsend, mq_timedreceive, mq_getattr, mq_setattr, mq_notify
总是返回最高优先级的消息;
4. Posix共享内存:
1)内存映射文件方式; open + mmap;持续性随文件;
2)共享内存区对象,即内存映射对象方式; shm_open + mmap;持续性随内核;----------------------- 一个进程修改了共享内存,需要通知其他进程此共享内存发生变化。
3)可以通过ftruncate修改共享内存对象的大小;
5. System V共享内存:
1)共享内存对象的大小在调用shmget创建时固定下来的;
同步:
1. System V sem: ------ 内核中维护,可以用于进程或线程的同步;
1)文件方式:先创建文件,然后ftok,semget,semctl,semop
2. 互斥锁:
- 互斥锁是协作锁,无法强制使用;
- 进程间使用时,锁及锁属性都必须放在共享内存中;
pthread_mutexattr_init,pthread_mutexattr_setpshared,pthread_mutexattr_setrobust_np
-
进程间使用时,都必须放在共享内存中;
- 条件变量唤醒时,可以唤醒一个线程,或所有线程;
6. Posix信号量:------ 都可以用于进程或线程的同步;
1)有名信号量:存放于文件系统;sem_open,sem_close,sem_unlink;随内核的;只有sem_unlink才真正删除sem;自动分配内存; ---- 相对好用一些
2)基于内存的信号量:存放于共享内存中;sem_init, sem_destory;调用者分配内存;调用者决定是在进程间,还是进程内使用; --- 调用者分配内存,一般为共享内存的一部分。sem_init的第二个参数int shared如果为0,则为进程内线程共享;如果为1,则必须在共享内存,供进程访问,用于进程间共享!