进程间通信

本文介绍了Unix系统中的进程间通信(IPC)方式,包括有名管道、无名管道、消息队列和共享内存。无名管道适用于有血缘关系的进程,而有名管道允许无关联进程通信。消息队列提供了双向通信和格式化的数据传递,而共享内存则是最快的一种IPC形式,但需要自行处理同步问题。通过示例代码展示了各种通信方式的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程间通信的应用场景:数据传输,共享数据,通知事件,资源共享,进程控制
同一主机进程间通信:
unix进程间通信方式:有名管道,无名管道,信号。
system V进程间通信方式和POSIX进程间通信方式有
消息队列,共享内存,信号量。
不同主机(网络)进程间通信:Socket


无名管道:pipe创建管道  fork创建子进程
只能用于具有血缘关系的进程之间通信
生命周期随进程,进程退出,管道释放
管道是半双工的,数据只能从一个方向传输
管道是基于字节流的
管道是自带同步机制的,在保证数据安全的前提下,按照特定顺序访问临界资源

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h> //exit

int main ()
{
	int fds[2];
	pipe(fds);

	pid_t pid = fork();
	if(pid == 0)//child
	{
		char buf[10] = {0};
		read(fds[0], buf, sizeof(buf));
		printf("child read= %s\n", buf);
		exit(0);

	}else if(pid > 0)//parent
	{
		write(fds[1], "hello", 5);
		wait(NULL);//
		exit(0);
	}else
	{
		perror("fork error\n");
		exit(1);
	}

}


有名管道:mkfifo创建管道   access判断文件是否存在  read write
是一种半双工的通信方式,但是允许无血缘关系进程间通信
有名管道是一种特殊类型的文件,与无名管道基本相似

//read.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>//pipe
#include <stdlib.h>//exit

//mkfifo  tmp
//先读后写
int main ()
{
	int fd = open("tmp", O_RDWR);
	if(fd < 0)
	{
		perror("open error\n");
		exit(1);
	}
	
	char buf[10] = {0};
	read(fd, buf, sizeof(buf));
	printf("read buf =%s\n", buf);

	close(fd);

	return 0;

}

//write.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>//pipe
#include <stdlib.h>//exit

int main ()
{
	int fd = open("tmp", O_RDWR);
	if(fd < 0)
	{
		perror("open error\n");
		exit(1);
	}

	write(fd, "hello", 5);
	close(fd);

	return 0;

}

消息队列:

消息队列是消息的链表,存放在内核中并由消息队列标识符表示。
特点:生命周期随内核,消息队列会一直存在,需要我们显示的调用接口删除或使用命令删除
消息队列可以双向通信
克服了管道只能承载无格式字节流的缺点

ipcs:显示IPC资源
ipcrm:手动删除IPC资源

msgtype > 0
接收消息类型为msgtype的消息
msgtype==0
接收消息队列中最前面的那个消息
msgtype<0
例-5(会读绝对值|-5|的一到四)

//read
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/msg.h>
//read.c -o read
//write.c  -o write 
//ipcs存在这里
struct msgbuf
{
	long mtype;
	char mtext[100];
};
int main ()
{
	int id = msgget(0x123456, IPC_CREAT | IPC_PRIVATE);

	struct msgbuf buf;
		
	msgrcv(id, &buf, sizeof(buf), 10, IPC_NOWAIT);
	printf("buf.mtype =%d, buf.mtext= %s\n", buf.mtype, buf.mtext);

	return 0;
}
//write
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>

struct msgbuf
{
	long mtype;
	char mtxt[100];
};

int main ()
{
	int id = msgget(0x123456, IPC_PRIVATE);

	struct msgbuf buf;
	buf.mtype = 10;
	strcpy(buf.mtxt, "hello");

	msgsnd(id, &buf, sizeof(buf), IPC_NOWAIT);


	return 0;
}


共享内存:
在对个处理器的计算机系统中,可以被不同的CPU访问的大容量空间。就是说一块物理内存被映射到两个进程的地址空间,两个进程都可以访问这段空间,从而实现进程间通信
特点:
共享内存是最快的IPC形式,因为内存映射到共享它的进程的地址空间,这些进程数据传递就不再涉及到内核了,也就是说说不再通过执行进入内核的系统调用来传递彼此的数据,所以,它的速度是最快的。
共享内存的生命周期随进程,也需要显示地删除。
共享内存没有互斥与同步机制,因此,我们在使用时,需要自己添加。

//read
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/ipc.h>

int main ()
{
	int id = shmget(0x8989, 4096, IPC_PRIVATE | IPC_CREAT);

	char *p = shmat(id, NULL, 0);
	printf("p= %s\n", p);

	shmdt(p);//解除映射

	return 0;
}
//write
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>

int main ()
{
	int id = shmget(0x8989, 4096, IPC_PRIVATE | IPC_CREAT);

	char *p = shmat(id, NULL, 0);
	strcpy(p, "aaaa");
	shmdt(p);//解除映射

	return 0;
}

信号:

是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生
按键  CTRL +c  CTRL + z
系统调用 kill raise abort
软件条件产生 alarm
硬件异常 段错误
可以使用kill -l命令查看Linux中的信号列表。

#include <stdio.h>
#include <signal.h>

//pkill +文件名 杀死文件
//kill  +编号  +进程号

void handler(int signum)
{
	printf("signum = %d\n", signum);

}

int main ()
{
	signal(SIGINT, handler);
//	signal(SIGINT, SIG_IGN);//忽视信号
//	signal(SIGINT, SIG_DFL);//默认信号
//	signal(SIGKILL, SIG_DFL);//	SIGKILL  SIGSTOP//不能捕获和忽视
	
//	SIGKILL  SIGSTOP//不能捕获和忽视
	while(1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值