IPC通信--管道、消息队列、共享内存

管道

两个进程通信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);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值