- 管道 pipe(命名管道和匿名管道);
- 信号 signal;
- 共享内存;
- 消息队列;
- 信号量 semaphore;
- 套接字 socket;
1. 管道
内核提供,单工,自同步机制。
1.1 匿名管道
磁盘上无法看到,只能有亲缘关系的进程才能用匿名管道。一般用于父子进程间通信。
pipe(2) 系统调用可以创建一个匿名管道 pipefd,文件描述符 pipefd[0] 为读管道,pipefd[1] 为写管道。
#include <unistd.h>
int pipe(int pipefd[2]);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
例子,父进程通过管道发送 hello 给子进程:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int pipefd[2];
if (pipe(pipefd) < 0) {
perror("pipe");
exit(1);
}
pid = fork();
if (pid > 0) {
// parent
close(pipefd[0]);
write(pipefd[1], "hello", 5);
close(pipefd[1]);
wait(NULL);
exit(0);
}
else if (pid == 0) {
// child
close(pipefd[1]);
char buf[50];
int len = read(pipefd[0], buf, 50);
printf("%d\n", len);
write(1, buf, len);
close(pipefd[0]);
exit(0);
}
else {
perror("fork");
exit(1);
}
exit(0);
}
1.2 命名管道
磁盘上能看到,文件类型为 p 的文件。
mkfifo(3) 函数可以创建一个 fifo 特殊文件(命名管道)。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
2 XSI -> SysV
2.1 消息队列,message queue
主动端,先发包的一方;被动端,先收包的一方;消息队列可以用于没有亲缘关系的进程间通信。
例子,proto.h,包含了传递的内容:
#ifndef PROTO_H__
#define PROTO_H__
#define KEYPATH "/etc/services"
#define KEYPROJ 'g'
#define NAMESIZE 32
struct msg_st
{
long mtype;
char name[NAMESIZE];
int math;
int chinese;
};
#endif
receiver.c,接收者:
#include <stdio.h>
#include <stdlib.h>
#include "proto.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main()
{
key_t key;
int msgid;
struct msg_st rbuf;
key = ftok(KEYPATH, KEYPROJ);
if (key < 0) {
perror("ftok");
exit(1);
}
msgid = msgget(key, IPC_CREAT | 0600);
if (msgid < 0) {
perror("msgget");
exit(1);
}
while (1)
{
if (msgrcv(msgid, &rbuf, sizeof(rbuf) - sizeof(long), 0, 0) < 0)
{
perror("msgrcv");
exit(1);
}
printf("NAME = %s\n", rbuf.name);
printf("MATH = %d\n", rbuf.math);
printf("CHINESE = %d\n", rbuf.chinese);
}
msgctl(msgid, IPC_RMID, NULL);
exit(0