Linux进程间通信(IPC)
最近学习了Linux进程,也对exec族函数、system函数、popen函数等有了⼀定的了解,但是他们都不能更好的相互传数据。现在学习⼀下进程间的通信(IPC)。
进程间通信: 不同进程之间传数据、交换信息。
⽅式: 管道(⽆名管道和命名管道),消息队列,信号量,共享内存,socket,steams等。其中socket 和 steams ⽀持不同主机上的两个进程通信。
⼀.管道(⽆名管道):
通常指⽆名管道,是Unix 系统 IPC最古⽼的形式。
头⽂件:
#include<unistd.h>
原型:
int pipe(int pipefd[2]);
特点:
1. 半双⼯,只能要么接收数据,要么传输数据。⼀个读,⼀个写。
2. 只能⽤于具有亲缘关系的进程通信,⽐如 ⽗⼦进程。
3. 可以看成是特殊⽂件,它读写可以使⽤read write等函数,但它不是普通⽂件和系统⽂件,它是只存在内存中的。
我们代码实现⽗进程写⼊hello word 给 ⼦进程。(⽆名管道)
**1.**开管道
2. 关闭⼦进程的写管道
3. 开始读管道接收⽗进程传的信息。
4. 关闭⽗进程的读取通道
5. 写hello word 给⼦进程。
6. ⼦进程读取数据hello word。
7. 输出读取的内容 hello word
代码:
运⾏过程及结果:
⼆.FIFO(命名管道):
**命名管道,是⼀种⽂件类型。
头⽂件:
**  #include <sys/types.h>
#include<sys/stat.h>
原型:
**`**int mkfifo(const char* pathname,mode_t mode);`
**pathname:**⽂件名
**mode:**权限 ⽐如 0600 就是可读可写。
特点: 可以在⽆关进程中交互数据,和⽆名管道不⼀样。
有路径名,是以特殊的⽂件形式存放在⽂件系统中。
创建命名管道:
结果:
注意:如果已经存在这个⽂件,创建会失败的。
当我们打开这个管道的时候,如果没有指定**O_NONBLOCK(**⾮阻塞标志),
如果你是只读的⽅式打开,它会⼀直阻塞到有另⼀个进程为写⽽打开此管道。如果你是只写的⽅式打开,它会⼀直阻塞到有另⼀个进程为读⽽打开此管道。
我们⽤代码实现⼀个写,写hello,word 给另⼀个进程。 让另⼀个读取并且输出。
代码:
做读取的代码
写进程代码:
当我们去运⾏读取的程序,会⼀直阻塞,等待写的程序运⾏。
读取⽅结果:
写⽅结果:
三.消息队列:
消息队列是消息的链接表,是存在内核中的,⼀个消息队列是由⼀个标识符(ID号)来标识。
头⽂件:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
原型:
**1.int msgget(key_t key,int msgflg);**
功能: ⽤于创建⼀个新的或打开⼀个已经存在的消息队列,此消息队列与key相对应。
创建成功返回队列的ID,失败返回-1
key: 函数ftok的返回值(ID号)或IPC_PRIVATE。
msgflag: IPC_CREAT:创建新的消息队列。
IPC_EXCL:与IPC_CREAT⼀同使⽤,表⽰如果要创建的消息队列已经存在,则返回错误。 IPC_NOWAIT:读写消息队列要求⽆法满⾜时,不阻塞。返回值: 调⽤成功返回队列标识符,否则返回-1.
添加消息:
**2.int msgsnd(int msqid,const void*msgp, size_t msgsz,int msgflg);**
成功返回0,失败返回-1。
读取消息:
**3. ssize_t msgrcv(int msqid,void*msgp, size_t msgsz,long msgtyp,
int msgflg);**
成功返回数据的长度,失败返回-1.
参数:
**msqid:**消息队列的识别码(ID)。
**msgp:**指向消息缓冲区的指针,此位置⽤来暂时存储发送和接收的消息,是⼀个⽤户可定义的通⽤结构,形态如下。
struct msgbuf
{
long mtype;/* 消息类型,必须 > 0 */
char mtext[1];/* 消息⽂本 *
};
**m
sgsz:消息的⼤⼩。
msgtyp: 消息类型
msgflg:这个参数依然是控制函数⾏为的标志,取值可以是:0,表⽰忽略。
进程通信方式
控制消息队列: