管道
两个进程通信pipe,两个半双工管道
int pipe(int fd[2]);
管道1:父fd1[1]->pipe1->子fd1[0]
管道2:子fd2[1]->pipe2->父fd2[0]
//建立管道读写文件描述符
int fd1[2], fd2[2];
pid_t childpid;
//创建两个管道
pipe(fd1);
pipe(fd2);
//fork
//子进程关闭管道1的写,管道2的读
if ((childpid = fork()) == 0){
close(fd1[1]);
close(fd2[0]);
server(fd1[0], fd2[1]);
exit(0);
}
//父进程关闭管道1的读,管道2的写
close(fd1[0]);
close(fd2[1]);
client(fd2[0], fd1[1]);
waitpid(childpid,null,0);
exit(0);
命名管道fifo, 有文件名与之关联,允许无亲缘关系进程访问一个管道,半双工
int mkfifo(const char* pathname, mode_t mode);
使用open打开文件路径
int open(pathname, mode, 0); mode(O_RDONLY:O_WRONLY)设置为读 / 写
无亲缘通信
//服务端
//建立两个fifo管道
mkfifo(FIFO1_name, FILE_MODE);
mkfifo(FIFO2_name, FILE_MODE);
//建立连接描述符
int readfd = open(FIFO1_name, O_RDONLY);
int writefd = open(FIFO2_name, O_WRONLY);
//处理
serverDoSomething(readfd, writefd);
exit(0);
//客户端,不需要建立管道,直接open文件名进行操作
//建立连接描述符
int readfd = open(FIFO2_name, O_RDONLY);
int writefd = open(FIFO1_name, O_WRONLY);
//处理
clientDoSomething(readfd, writefd);
//结束
close(fd);
unlink(FIFO_name);
exit(0);
系统加与pipe和fifo的限制在于
1.OPEN_MAX 任意时刻打开的最大描述符
2.PIPE_BUFF 写入管道的最大数据量
消息队列
消息队列:一个存放消息的容器,内核可以理解是消息链表,拥有足够特权的任意进程可以操作消息队列
struct mymesg{
long int type;
char mtext[size];
};
posix:读总是返回最高优先级
mq_open 创建、打开队列
mq_close 关闭
mq_unlink 删除队列
mq_send 发生消息
mq_receive 接受消息
//读写
mqd_t mqd = mq_open("./tmp", O_WRONLY);
const char* msg = "helloworld";
//发
mq_send(mqd, msg, sizeof(msg), 1);
//收
char buf[BUFSIZE];
unsigned int prio;
mq_receive(mqd, buf, BUFSIZE, &prio);
mq_close(mqd);
system V:读总可以返回指定优先级
//1,生成键值
key_t ftok(const char* path, int id);
path:已存在路径名
//2.创建或访问消息队列
int msgget(key_t key, int oflag);
oflag操作权限,返回消息队列id
//3.发送消息
int msgsnd(int msqid, const void* ptr, size_t length, int flag);
ptr:消息结构体的指针
length:消息结构体mtext的大小
flag: 0表示消息队列满时阻塞,IPC_NOWAIT表示不会等待,立即退出
//4.从队列读取消息
int msgrcv(int msqid, const void* ptr, size_t length,long type, int flag);
type:表示返回的消息类型
//5.控制
msgctl
常用于关闭消息队列
共享内存
共享内存接口函数
//1.把文件对象映射到调用进程的地址空间并返回内存区的起始地址
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
addr–映射内存区的起始地址,一般设为0
len–文件长度
prot–内存映射区的保护,读 / 写
flags–进程的改动是否同步到映射内存
fd–文件描述符
offset–文件映射偏移
//2.从某个进程的地址空间解除映射
int munmap(void *addr, size_t len);
mmap的地址和映射区的大小
//posix
无亲缘关系共享内存
1, 内存映射文件,由open打开,将得到的描述符映射到当前进程地址空间
2,共享内存区映射,shm_open打开一个文件系统的路径名,描述符映射到当前进程地址空间
//建立共享内存区映射文件
shm_unlink(Px_ipc_name(argv[1]));
fd1 = shm_open(Px_ipc_name(argv[1]), _oflag, _mode);
ftruncate(fd1, size);//设置文件大小
//建立内存映射文件
fd2 = open("/etc/motd", O_RDONLY);
fstat(fd2, &stat);//获取信息
//父子进程
if ((pid = fork()) == 0){
int *ptr1 = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
int *ptr2 = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd2,0);
//do something...
sleep(5);//等待父进程写一个数
printf("%d/n", *ptr1);
exit(0);
}
int *ptr1 = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
int *ptr2 = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd2,0);
*ptr1 = 777;
waitpid(pid, null, 0);
exit(0);
//使用BSD方式可以不指定固定文件路径
//MAP_ANON & fd=-1
int *ptr1 = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);