进程通信实验代码 linux
时间: 2024-01-31 17:02:38 浏览: 29
进程通信是指进程之间通过特定的方式进行数据交换或共享资源的过程。在 Linux 中,进程通信主要有管道、信号、共享内存、消息队列、套接字等方式。下面是几种进程通信的示例代码:
1、管道通信
管道通信是一种单向的通信方式,通信的两个进程分别对应管道的两端,一个进程向管道中写入数据,另一个进程从管道中读取数据。在 Linux 中,管道可以使用 pipe 函数创建,示例代码如下:
```
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
int fd[2];
pid_t pid;
char buf[20];
if (pipe(fd) < 0) {
printf("pipe error\n");
exit(1);
}
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(1);
}
else if (pid > 0) { // 父进程
close(fd[0]); // 关闭读端
write(fd[1], "hello world\n", 12); // 写入数据到管道中
wait(NULL);
}
else { // 子进程
close(fd[1]); // 关闭写端
read(fd[0], buf, 20); // 从管道中读取数据
printf("%s", buf);
}
return 0;
}
```
2、信号通信
信号通信是指在进程之间传递信号,通常用于进程间的异步通信。在 Linux 中,可以使用 kill 函数发送信号,可以使用 signal 函数捕捉信号。示例代码如下:
```
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler(int signo)
{
printf("received signal %d\n", signo);
}
int main()
{
pid_t pid;
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(1);
}
else if (pid > 0) { // 父进程
sleep(1);
kill(pid, SIGINT); // 发送信号给子进程
}
else { // 子进程
signal(SIGINT, handler); // 捕捉信号
while(1) {
printf("child process running\n");
sleep(1);
}
}
return 0;
}
```
3、共享内存通信
共享内存通信是指多个进程共享同一块内存区域,从而实现数据共享的过程。在 Linux 中,可以使用 shmget 函数创建共享内存,可以使用 shmat 函数将共享内存映射到进程的地址空间中。示例代码如下:
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/wait.h>
int main()
{
int shmid;
pid_t pid;
char *shmaddr;
if ((shmid = shmget(IPC_PRIVATE, 1024, 0666|IPC_CREAT)) < 0) { // 创建共享内存
printf("shmget error\n");
exit(1);
}
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(1);
}
else if (pid > 0) { // 父进程
wait(NULL);
if ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1) { // 映射共享内存
printf("shmat error\n");
exit(1);
}
printf("%s", shmaddr);
shmdt(shmaddr); // 解除映射
shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
}
else { // 子进程
if ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1) { // 映射共享内存
printf("shmat error\n");
exit(1);
}
sprintf(shmaddr, "hello world\n"); // 写入数据到共享内存
exit(0);
}
return 0;
}
```
4、消息队列通信
消息队列通信是指进程间通过消息队列来传递消息的过程。在 Linux 中,可以使用 msgget 函数创建消息队列,可以使用 msgsnd 函数向消息队列中发送消息,可以使用 msgrcv 函数从消息队列中接收消息。示例代码如下:
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/wait.h>
struct msgbuf {
long mtype;
char mtext[1024];
};
int main()
{
int msgid;
pid_t pid;
struct msgbuf msg;
if ((msgid = msgget(IPC_PRIVATE, 0666|IPC_CREAT)) < 0) { // 创建消息队列
printf("msgget error\n");
exit(1);
}
if ((pid = fork()) < 0) {
printf("fork error\n");
exit(1);
}
else if (pid > 0) { // 父进程
wait(NULL);
if (msgrcv(msgid, &msg, 1024, 1, 0) < 0) { // 从消息队列中接收消息
printf("msgrcv error\n");
exit(1);
}
printf("%s", msg.mtext);
msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
}
else { // 子进程
msg.mtype = 1;
sprintf(msg.mtext, "hello world\n");
if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) < 0) { // 向消息队列中发送消息
printf("msgsnd error\n");
exit(1);
}
exit(0);
}
return 0;
}
```
5、套接字通信
套接字通信是指进程间通过套接字来传递数据的过程。在 Linux 中,套接字可以是基于网络协议的套接字,也可以是基于本地协议的套接字。示例代码如下:
```
// 服务器端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8888
int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cliaddr;
char buf[1024];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { // 创建套接字
printf("socket error\n");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { // 绑定地址和端口号
printf("bind error\n");
exit(1);
}
if (listen(sockfd, 5) < 0) { // 监听套接字
printf("listen error\n");
exit(1);
}
socklen_t clilen = sizeof(cliaddr);
if ((connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen)) < 0) { // 接受客户端的连接请求
printf("accept error\n");
exit(1);
}
while(1) {
if (read(connfd, buf, sizeof(buf)) < 0) { // 读取客户端发送的数据
printf("read error\n");
exit(1);
}
printf("%s", buf);
if (write(connfd, buf, strlen(buf)) < 0) { // 向客户端发送数据
printf("write error\n");
exit(1);
}
}
close(sockfd);
close(connfd);
return 0;
}
// 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#define PORT 8888
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char buf[1024];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { // 创建套接字
printf("socket error\n");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(PORT);
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { // 连接服务器
printf("connect error\n");
exit(1);
}
while(fgets(buf, sizeof(buf), stdin) != NULL) {
if (write(sockfd, buf, strlen(buf)) < 0) { // 向服务器发送数据
printf("write error\n");
exit(1);
}
if (read(sockfd, buf, sizeof(buf)) < 0) { // 读取服务器返回的数据
printf("read error\n");
exit(1);
}
printf("%s", buf);
}
close(sockfd);
return 0;
}
```