经典IPC:管道、FIFO、消息队列、信号量、共享存储器。
一、pipe管道
#include <unistd.h>
int pipe(int filedes[2]);
返回值:若成功则返回0,若出错则返回-1;
这种管道有下面两种局限性:
1、历史上,它们是半双工的(即数据只能在一个方向上流动)。现在,某些系统提供全双工管道,但是为了最佳的可移植性,我们决不应预先假定系统使用此特性。
2、它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道通信,pipe管道一般用于父进程与子进程之间的通信。
二、popen和pclose函数
创建一个管道连接到另外一个进程,然后读其输出或向其输入端发送数据。
FILE *popen(const char *cmdstring, const char *type);
例如:FILE *popen("./child", "r");
“r”表示从其他进程(child.c)读取数据;
“w”表示向其他进程(child.c)发送数据;
./child 是一个当前目录下的可执行性文件;
返回值:若成功返回文件指针,出错返回NULL;
int pclose(FILE *fp);
返回值:成功返回cmdstring的终止状态, 出错返回-1;
三、FIFO
FIFO有时被称为命名管道。
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
例:if(access(RFIFO, F_OK) != 0)
{//如果RFIFO不存在
mkfifo(RFIFO, 0777);
}
一旦已经用mkfifo创建了一个FIFO,就可以用open打开它。
四、消息队列
创建两个进程send.c、recv.c
send.c用于发送消息,recv.c用于接收消息;
send发送消息队列:
1、构建消息的结构体
struct msgtype
{
long type;用于指明是哪条消息
char dat[100];用于存放消息
};
2、构建消息队列的KEY
例如:
key_t key;
key = ftok("msg", 1);
其中msg必须是已经存在的文件;
第二个参数必须不为0;
3、创建消息队列
例如:
msgid = msgget(key, IPC_CREAT | 0777);
其中msgget函数返回一个id赋给msgid;
4、构建消息
例如:
struct msgtype msg ={0};
msg.type = 1;
strcpy(msg.dat, "hello world 1\n");
5、将构建好的消息发送至构建好的队列上去
例如:
msgsnd(msgid, &msg, sizeof(msg.dat), 0);
recv从消息队列接收消息
1、同发送进程一样构建消息结构体并赋初值;
2、获取消息队列;
3、从消息队列上接收消息队列存放于消息结构体中
msgrcv(msgid, &msg, sizeof(msg.dat), 0,IPC_NOWAIT);
其中第三个参数为0,表示可以接受第一条消息,若为1,则只接受发送进程中类型为msg.type == 1的那条消息;
第四个参数表示不等待;
删除消息队列
例如:
msgct(msgid, IPC_RMID, NULL);
共享内存
1、构建共享内存的KEY
2、创建或者获取共享内存
例如:
shmid = shmget(key, 1024 * 1024, IPC_CREAT | 0777);
3、把创建好的共享内存映射到本进程空间
例如:
void *addr = NULL;
addr = shmat(shmid, NULL, 0);