实验五-进程间通信实验(二).doc
Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-date实验五-进程间通信实验(二)实验五 进程间通信实验实验五 进程间通信实验(二)实验目的: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_LEN256#define DELAY_TIME1int main()pid_t pid;int pipe_fd2;char bufMAX_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 errorn");exit(1);/* 创建一子进程 */if (pid = fork() = 0)/* 子进程关闭写描述符,并通过使子进程暂停1秒等待父进程已关闭相应的读描述符 */close(pipe_fd1);sleep(DELAY_TIME * 3);/* 子进程读取管道内容 */if (real_read = read(pipe_fd0, buf, MAX_DATA_LEN) > 0)printf("%d bytes read from the pipe is '%s'n", real_read, buf);/* 关闭子进程读描述符 */close(pipe_fd0);exit(0);else if (pid > 0)/* 父进程关闭读描述符,并通过使父进程暂停1秒等待子进程已关闭相应的写描述符 */close(pipe_fd0);sleep(DELAY_TIME);/* 父进程向管道中写入字符串 */if(real_write = write(pipe_fd1, data, strlen(const char*)data) != -1)printf("Parent wrote %d bytes : '%s'n", real_write, data);/*关闭父进程写描述符*/close(pipe_fd1);/*收集子进程退出信息*/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_SIZEPIPE_BUF /*定义在于limits.h中*/int main(int argc, char * argv) /*参数为即将写入的字符串*/int fd;char buffMAX_BUFFER_SIZE;int nwrite;if(argc <= 1)printf("Usage: ./fifo_write stringn");exit(1);sscanf(argv1, "%s", buff);/* 以只写阻塞方式打开FIFO管道 */fd = open(MYFIFO, O_WRONLY);if (fd = -1)printf("Open fifo file errorn");exit(1);/*向管道中写入字符串*/if (nwrite = write(fd, buff, MAX_BUFFER_SIZE) > 0)printf("Write '%s' to FIFOn", 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_SIZEPIPE_BUF /*定义在于limits.h中*/int main()char buffMAX_BUFFER_SIZE;int fd;int nread;/* 判断有名管道是否已存在,若尚未创建,则以相应的权限创建*/if (access(MYFIFO, F_OK) = -1) if (mkfifo(MYFIFO, 0666) < 0) && (errno != EEXIST)printf("Cannot create fifo filen");exit(1);/* 以只读阻塞方式打开有名管道 */fd = open(MYFIFO, O_RDONLY);if (fd = -1)printf("Open fifo file errorn");exit(1);while (1)memset(buff, 0, sizeof(buff);if (nread = read(fd, buff, MAX_BUFFER_SIZE) > 0)printf("Read '%s' from FIFOn", 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 SIGBUSn"); int main() printf("Waiting for signal SIGBUSn");/*注册信号处理函数*/ signal(SIGBUS,my_func); pause(); /将进程挂起,直到捕捉到信号为止 exit(0);1)对程序进行编辑和编译2)在一个终端中运行sig_bus,会看到进程挂起,等待信号。3)在另一个终端,查找到运行sig_bus的进程号,通过kill命令发送SIGBUS信号给这个进程。4)信号触发了处理函数。这时可以看到前面挂起的进程在接收到这个信号后的处理,用自定义的信号处理函数my_func里处理,因此打印出“I have get SIGBUS”。 -