当前位置:文档之家› 实验五-进程间通信实验(二)

实验五-进程间通信实验(二)

实验五-进程间通信实验(二)实验五进程间通信实验(二)实验目的:1.通过基础实验,基本掌握无名管道、有名管道的程序设计。

2.通过编写程序,使读者掌握信号处理程序设计方法。

实验内容:1.无名管道程序设计:在父进程中创建一个无名管道,并创建子进程;在父进程中写该管道,并用子进程将内容读出。

2.有名管道程序设计:创建两个进程,在A进程中创建一个有名管道,并向其写入数据,通过B进程从有名管道中读出数据。

3.信号处理程序设计:在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号来触发信号处理函数。

实验过程:(一)无名管道程序设计实验代码:/* pipe.c */#include <unistd.h>#include <sys/types.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_DATA_LEN 256#define DELAY_TIME 1int main(){pid_t pid;int pipe_fd[2];char buf[MAX_DATA_LEN];const char data[] = "Pipe Test Program"; int real_read, real_write;memset((void*)buf, 0, sizeof(buf));/* 创建管道*/if (pipe(pipe_fd) < 0){printf("pipe create error\n");exit(1);}/* 创建一子进程*/if ((pid = fork()) == 0){/* 子进程关闭写描述符,并通过使子进程暂停1秒等待父进程已关闭相应的读描述符*/ close(pipe_fd[1]);sleep(DELAY_TIME * 3);/* 子进程读取管道内容*/if ((real_read = read(pipe_fd[0], buf, MAX_DATA_LEN)) > 0){printf("%d bytes read from the pipe is '%s'\n", real_read, buf);}/* 关闭子进程读描述符*/close(pipe_fd[0]);exit(0);}else if (pid > 0){/* 父进程关闭读描述符,并通过使父进程暂停1秒等待子进程已关闭相应的写描述符*/close(pipe_fd[0]);sleep(DELAY_TIME);/* 父进程向管道中写入字符串*/ if((real_write = write(pipe_fd[1], data, strlen((const char*)data))) != -1){printf("Parent wrote %d bytes : '%s'\n", real_write, data);}/*关闭父进程写描述符*/close(pipe_fd[1]);/*收集子进程退出信息*/waitpid(pid, NULL, 0);exit(0);}}将该程序编译,运行。

#./pipe……(二)有名管道程序设计1.编写一个应用程序,包含两个程序,一个用于读管道,一个用于写管道。

其中在读管道的程序里创建管道,并且作为main()函数里的参数由用户输入要写入的内容。

读管道的程序会读出用户写入到管道的内容,这两个程序采用的是阻塞式读写管道模式。

实验代码:(1)写管道的程序/* fifo_write.c */#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <limits.h>#define MYFIFO "/tmp/myfifo" /* 有名管道文件名*/#define MAX_BUFFER_SIZE PIPE_BUF /*定义在于limits.h中*/int main(int argc, char * argv[]) /*参数为即将写入的字符串*/{int fd;char buff[MAX_BUFFER_SIZE];int nwrite;if(argc <= 1){printf("Usage: ./fifo_write string\n");exit(1);}sscanf(argv[1], "%s", buff);/* 以只写阻塞方式打开FIFO管道*/fd = open(MYFIFO, O_WRONLY);if (fd == -1){printf("Open fifo file error\n");exit(1);}/*向管道中写入字符串*/if ((nwrite = write(fd, buff, MAX_BUFFER_SIZE)) > 0){printf("Write '%s' to FIFO\n", buff);}close(fd);exit(0);}(2)读管道的程序/* fifo_read.c */#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <limits.h>#define MYFIFO "/tmp/myfifo"#define MAX_BUFFER_SIZE PIPE_BUF /*定义在于limits.h中*/int main(){char buff[MAX_BUFFER_SIZE];int fd;int nread;/* 判断有名管道是否已存在,若尚未创建,则以相应的权限创建*/if (access(MYFIFO, F_OK) == -1){if ((mkfifo(MYFIFO, 0666) < 0) && (errno != EEXIST)){printf("Cannot create fifo file\n");exit(1);}}/* 以只读阻塞方式打开有名管道*/fd = open(MYFIFO, O_RDONLY);if (fd == -1){printf("Open fifo file error\n");exit(1);}while (1){memset(buff, 0, sizeof(buff));if ((nread = read(fd, buff, MAX_BUFFER_SIZE)) > 0){printf("Read '%s' from FIFO\n", buff);}}close(fd);exit(0);}为了能够较好地观察运行结果,需要把这两个程序分别在两个终端里运行,首先启动读管道程序。

读管道进程在建立管道之后就开始循环地从管道里读出内容,如果没有数据可读,则一直阻塞到写管道进程向管道写入数据。

在启动了写管道程序后,读进程能够从管道里读出用户的输入内容。

# ./fifo_read……终端二#./fifo_write FIFO……#./fifo_write Test……#./fifo_write Program……(三)信号处理程序设计实验要求:编写一个应用程序,用signal 注册信号处理函数,并用kill发送相应信号触发信号处理。

❝信号概念。

信号是一种进程间的通信机制,它为应用程序提供一种异步的软件中断,使应用程序有机会接收其它程序或终端发送的命令(即信号)。

应用程序收到信号后,有三种处理方式:忽略、默认和捕捉。

进程收到一个信号后,会检查对该信号的处理机制。

如果是SIG_IGN,就忽略该信号;如果SIG_DFT,则采用系统默认的处理动作,通常是终止进程或忽略该信号;如果为该信号指定了一个处理函数(捕捉),则会中断当前进程正在执行的任务,转而去执行该信号的处理函数,返回后再继续执行被中断的任务。

❝常用信号说明:通过kill –l命令可以查看到Linux支持的信号列表。

实验代码及步骤:功能描述:在进程中为SIGBUS注册处理函数,并向该进程发送SIGBUS信号来触发信号处理函数。

/*sig_bus.c*/#include<signal.h>#include<stdio.h>#include<stdlib.h>/*自定义的信号处理函数*/void my_func(int sign_no){if(sign_no==SIGBUS){printf("I have get SIGBUS\n");}}int main(){printf("Waiting for signal SIGBUS\n");/*注册信号处理函数*/signal(SIGBUS,my_func);pause(); //将进程挂起,直到捕捉到信号为止exit(0);}1)对程序进行编辑和编译2)在一个终端中运行sig_bus,会看到进程挂起,等待信号。

3)在另一个终端,查找到运行sig_bus的进程号,通过kill命令发送SIGBUS信号给这个进程。

4)信号触发了处理函数。

这时可以看到前面挂起的进程在接收到这个信号后的处理,用自定义的信号处理函数my_func里处理,因此打印出“I have get SIGBUS”。

相关主题