实验三:进程通信实验

实验三 .进程通信实验

一、学习fork()函数,了解如何编程实现进程创建

参考这篇博客linux中fork()函数详解(原创!!实例讲解)_linux fork()函数-CSDN博客

fork入门知识

​ 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
​ 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

让我们来看下面这个例子

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

int value=5;     //where?

int main(){
	
	int i;     //where?
	
	pid_t pid;
	
	for(i=0;i<2;i++){    // How many new processes and printfs?
		pid=fork();
	
		if(pid==0){
			value += 15;
			printf("Child: value = %d\n",value);
		}
		else if(pid>0){
			wait(NULL);
			printf("PARNET: value = %d\n",value);
			exit(0);   //Notice:What will happen with or without this line?
		}
	}
}

运行结果:
在这里插入图片描述

通过本例可以一窥fork函数在循环中的执行顺序及原理,这里建议看看原大佬博客的笔记,写的十分详细且易懂

二、学习管道的编程思想,并实现进程间通信

管道(Pipe) 管道介绍 管道pipe是进程间通信最基本的⼀种机制。两个进程可以通过管道,⼀个在管道⼀端向管道发送其数据(写入 管道),⽽另⼀个进程可以在管道的另⼀端从管道读取数据。 管道以半双⼯的⽅式⼯作,即它的数据流是单向的。因此使⽤管道时的规则⼀般是读管道数据的进程关闭管道 的写入端,⽽写管道进程关闭其读端⼝

管道pipe系统语法说明 pipe系统调⽤的语法为

#include <unistd.h> 
int pipe(int pipe_id[2]); 

如果pipe系统调⽤执⾏成功,返回0,pipe_id[0]和pipe_id[1]中将放入管道两端的描述符。 出错返回-1。

下面是⼀段由并发的⽗⼦进程合作将整数X的值从1加到10的⽰意程序。其中的⽗⼦进程开展协作时,两者之间通过管道进⾏通信。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int pid;
int pipe1[2];
int pipe2[2];
int x;
if (pipe(pipe1) < 0) {
perror("failed to create pipe1");
exit(EXIT_FAILURE);
}
if (pipe(pipe2) < 0) {
perror("failed to create pipe2");
exit(EXIT_FAILURE);}
pid = fork();
if (pid < 0) {
perror("failed to create new process");
exit(EXIT_FAILURE);
} else if (pid == 0) {
// ⼦进程=>⽗进程:⼦进程通过pipe2[1]进⾏写
// ⼦进程<=⽗进程:⼦进程通过pipe1[0]读
// 因此,在⼦进程中将pipe1[1]和pipe2[0]关闭
close(pipe1[1]);
close(pipe2[0]);
do {
read(pipe1[0], &x, sizeof(int));
printf("child %d read: %d\n", getpid(), x++);
write(pipe2[1], &x, sizeof(int));
} while (x <= 9);
close(pipe1[0]);
close(pipe2[1]);
} else {
// ⽗进程<=⼦进程:⽗进程从pipe2[0]读取⼦进程传过来的数
// ⽗进程=>⼦进程:⽗进程将更新的值通过pipe1[1]写入,传给⼦进程
// 因此,⽗进程会先关闭pipe1[0]和pipe2[1]端⼝
close(pipe1[0]);
close(pipe2[1]);
x = 1;
do {
write(pipe1[1], &x, sizeof(int));
read(pipe2[0], &x, sizeof(int));
printf("parent %d read: %d\n", getpid(), x++);
} while (x <= 9);
close(pipe1[1]);
close(pipe2[0]);
}
return EXIT_SUCCESS;
}

运行结果:

在这里插入图片描述

三、进程通信实例

小作业:

设有⼆元函数 f(x,y) = f(x) + f(y), 其中:

f(x) = f(x-1)*x  (x>1) 
f(x) = 1  (x=1) 
f(y) = f(y-1) + f(y-2)   (y>2) 
f(y) = 1   (y=1,2)     

请编程建立3个并发协作进程,它们分别完成 f(x,y)、f(x)、f(y)

笔者解法:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 计算 f(x)
int f_x(int x) {
    if (x > 1)
        return f_x(x - 1) * x;
    else
        return 1;
}

// 计算 f(y)
int f_y(int y) {
    if (y > 2)
        return f_y(y - 1) + f_y(y - 2);
    else
        return 1;
}

int main() {
    int x = 5, y = 5; // 你可以根据需要改变 x 和 y 的值
    int pipe_fd1[2], pipe_fd2[2];

    // 创建两个无名管道
    if (pipe(pipe_fd1) == -1 || pipe(pipe_fd2) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    pid_t pid1, pid2;

    // 创建第一个子进程来计算 f(x)
    if ((pid1 = fork()) == 0) {
        close(pipe_fd1[0]); // 关闭读端
        int result_x = f_x(x);
        write(pipe_fd1[1], &result_x, sizeof(result_x));
        close(pipe_fd1[1]); // 关闭写端
        exit(EXIT_SUCCESS);
    } else if (pid1 < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    // 创建第二个子进程来计算 f(y)
    if ((pid2 = fork()) == 0) {
        close(pipe_fd2[0]); // 关闭读端
        int result_y = f_y(y);
        write(pipe_fd2[1], &result_y, sizeof(result_y));
        close(pipe_fd2[1]); // 关闭写端
        exit(EXIT_SUCCESS);
    } else if (pid2 < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    // 父进程读取子进程的结果并计算 f(x, y)
    close(pipe_fd1[1]); // 关闭写端
    close(pipe_fd2[1]); // 关闭写端

    int result_x, result_y;
    read(pipe_fd1[0], &result_x, sizeof(result_x));
    read(pipe_fd2[0], &result_y, sizeof(result_y));
    close(pipe_fd1[0]); // 关闭读端
    close(pipe_fd2[0]); // 关闭读端

    int result = result_x + result_y;

    printf("f(x,y) = f(x) + f(y) = %d + %d = %d\n", result_x, result_y, result);

    return 0;
}

运行结果:

在这里插入图片描述

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值