实验五--进程间通信_第1页
实验五--进程间通信_第2页
实验五--进程间通信_第3页
实验五--进程间通信_第4页
实验五--进程间通信_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

实验五 进程间通信UNIX/LINUX系统的进程间通信机构(IPC)允许在任意进程间大批量地交换数据。本实验的目的是了解和熟悉LINUX支持的信号机制、管道机制、消息队列通信机制及共享存储区机制。5.1信号机制实验(一)【实验目的】1了解什么是信号。2熟悉LINUX系统中进程之间软中断通信的基本原理。【实验原理】利用signal来实现发送信号和接受信号的原理【实验内容】1编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止: Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止: Parent process is killed! # include# include# includeint wait_mark;void waiting(),stop();void main() int p1, p2;signal(SIGINT,stop);while(p1=fork()=-1);if(p10)/*在父进程中*/ while(p2=fork()= =-1); If(p20)/*在父进程中*/ wait_mark=1; waiting(0); kill(p1,10); kill(p2,12); wait( ); wait( ); printf(“parent process is killed!n”); exit(0); else/*在子进程2中*/ wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf(“child process 2 is killed by parent!n”);lockf(1,0,0);exit(0); else/*在子进程1中*/ wait_mark=1; signal(10,stop); waiting(); lockf(1,1,0); printf(“child process 1 is killed by parent!n”); lockf(1,0,0); exit(0);void waiting() while(wait_mark!=0);void stop() wait_mark=0;实验要求: 运行程序并分析结果。 如果把signal(SIGINT,stop)放在号和号位置,结果会怎样并分析原因。 该程序段前面部分用了两个wait(0),为什么? 该程序段中每个进程退出时都用了语句exit(0),为什么?5.2信号机制实验(二)【实验目的】学习signal的函数的使用【实验原理】利用signal的函数的机制来实习我们发送截获信号的功能【实验内容】修改上面的程序,增加语句signal(SIGINT,SIG_IGN)和语句signal(SIGQUIT,SIG_IGN),再观察程序执行时屏幕上出现的现象,并分析其原因。# include# include# includeint pid1, pid2;int EndFlag=0;pf1=0;pf2=0;void IntDelete() kill(pid1,10); kill(pid2,12);EndFlag=1;void Int1() printf(“child process 1 is killed by parent !n”); exit(0);void Int2() printf(“child process 2 is killed by parent !n”); exit(0);main() int exitcode; signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN);while(pid1=fork()=-1); if(pid1=0) signal(SIGUSR1,Int1);signal(SIGINT,SIG_IGN);pause();exit(0); else while(pid2=fork()= =-1); if(pid2=0) signal(SIGUSR2,Int2);signal(SIGINT,SIG_IGN);pause();exit(0); else signal(SIGINT,IntDelete); waitpid(-1,&exitcode,0);/*等待任何子进程中断或结束*/ printf(“parent process is killed n”); exit(0); 实验要求:运行程序并分析结果。司机售票员问题(选做题)编程用fork()创建一个子进程代表售票员,司机在父进程中,再用系统调用signal()让父进程(司机)捕捉来自子进程(售票员)发出的中断信号,让子进程(售票员)捕捉来自(司机)发出的中断信号,以实现进程间的同步运行。5.3管道通信实验(一)【实验目的】1、了解什么是管道2、熟悉UNIX/LINUX支持的管道通信方式【实验内容】编写程序实现进程的管道通信。用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。参考程序#include #include #include int pid1,pid2;main( ) int fd2;char outpipe100,inpipe100;pipe(fd); /*创建一个管道*/while (pid1=fork( )= =-1);if(pid1= =0)lockf(fd1,1,0); sprintf(outpipe,child 1 process is sending message!); /*把串放入数组outpipe中*/ write(fd1,outpipe,50); /*向管道写长为50字节的串*/ sleep(5); /*自我阻塞5秒*/ lockf(fd1,0,0); exit(0);elsewhile(pid2=fork( )= =-1); if(pid2= =0) lockf(fd1,1,0); /*互斥*/ sprintf(outpipe,child 2 process is sending message!); write(fd1,outpipe,50); sleep(5);lockf(fd1,0,0); exit(0); else wait(0); /*同步*/ read(fd0,inpipe,50); /*从管道中读长为50字节的串*/ printf(%s/n,inpipe); wait(0); read(fd0,inpipe,50); printf(%s/n,inpipe); exit(0); 五、运行结果 延迟5秒后显示child 1 process is sending message! 再延迟5秒child 2 process is sending message!5.4管道通信实验(二)【实验目的】1、掌握有名管道的创建和读写方式2、熟悉UNIX/LINUX支持的有名管道通信方式【实验内容】1. 创建有名管道2. 本进程执行循环等待数据被写入到管道中并读有名管道3. 打开有名管道并写数据到名管道参考代码:/read_fifo.c#include #include #include #include #include #include #include #define BUFFER_SIZE1024int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, Usage: %s n, argv0); exit(1); /int open(const char *path, int oflag, .); if (fd = open(argv1, O_RDONLY) 0) fprintf(stderr, open fifo %s for reading failed: %sn, argv1, strerror(errno); exit(1); fprintf(stdout, open fifo %s for reading successed.n, argv0); char bufferBUFFER_SIZE; ssize_t n; while (1) again: /ssize_t read(int fd, void *buf, size_t count); if (n = read(fd, buffer, BUFFER_SIZE) 0) if (errno = EINTR) goto again; else fprintf(stderr, read failed on %s: %sn, argv1, strerror(errno);exit(1); else if (n = 0) fprintf(stderr, peer closed fifo.n); break; else buffern = 0; fprintf(stdout, read %d bytes from fifo: %sn, n, buffer); return 0;/ write_fifo.c#include #include #include #include #include #include #include #include #define BUFFER_SIZE1024void signal_handler(int s);int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, Usage: %s n, argv0); exit(1); signal(SIGPIPE, signal_handler); /int open(const char *path, int oflag, .); if (fd = open(argv1, O_WRONLY) 0) fprintf(stderr, open fifo %s for writting failed: %sn, argv1, strerror(errno); exit(1); fprintf(stdout, open fifo %s for writting successed.n, argv0); char bufferBUFFER_SIZE; ssize_t n; /char *fgets(char *s, int size, FILE * stream); while (fgets(buffer, BUFFER_SIZE, stdin) again: /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, buffer, strlen(buffer) 0) if (errno = EINTR) goto again; else fprintf(stderr, write() failed on fifo: %sn, strerror(errno);/ FIXME:break; return 0;void signal_handler(int s) fprintf(stdout, Caught signal %dn, s);/ create_fifo.c#include #include #include #include #include int main(int argc, char *argv) if (argc 2) fprintf(stdout, Usage: %s n, argv0); exit(1); /int mkfifo(const char *path, mode_t mode); if (mkfifo(argv1, 0644) 0) fprintf(stderr, mkfifo() failed: %sn, strerror(errno); exit(1); return 0;5.5共享内存通信实验【实验目的】1、掌握共享内存的创建和读写方式2、熟悉UNIX/LINUX支持的共享内存通信方式【实验内容】1. 创建共享内存2. 写入到共享内存3. 读数据从共享内存代码参考:/write.c#include #include #include #include #include #include #include #include #include #define MAPPED_FILENAME/tmp/test.mmap.1int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, Usage: %s n, argv0); exit(1); / XXX: step 1, open file, get a fd /int open(const char *pathname, int flags, mode_t mode); if (fd = open(argv1, O_RDWR | O_CREAT | O_EXCL, 0644) 0) if (errno = EEXIST) fprintf(stderr, Fatal error: The target mapped file existed, exit.n); else fprintf(stderr, Error: open file failed: (errno = %d)%sn, errno, strerror(errno); exit(1); off_t offset; offset = 1024; / XXX: step 2, create a hole file /off_t lseek(int fildes, off_t offset, int whence); if (lseek(fd, offset, SEEK_SET) = (off_t) - 1) fprintf(stderr, lseek() failed: %sn, strerror(errno); /FIXME: unlink the file close(fd); exit(1); ssize_t n; /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, , 1) 0) fprintf(stderr, write() failed: %sn, strerror(errno); exit(1); /* * On success, mmap returns a pointer to the mapped area. On error, the value MAP_FAILED (that is, (void*) -1) is returned, and errno is set appropriately. On success, munmap returns 0, on failure -1, and errno is set (probably to EINVAL). */* PROT_EXEC Pages may be executed. PROT_READ Pages may be read. PROT_WRITE Pages may be written. PROT_NONE Pages may not be accessed.*/ void *p; / XXX: step 3, mmap(), get a pointer /void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); if (p = mmap(NULL, 1024, PROT_WRITE, MAP_SHARED, fd, 0) = MAP_FAILED) fprintf(stderr, mmap() failed: %sn, strerror(errno); close(fd); exit(1); close(fd); fprintf(stdout, mapped file to memory, size = %dn, 1024); / XXX: step 4, read/write on shared memory char *banner = hello world.; /void *memcpy(void *dest, const void *src, size_t n); memcpy(p + 256, banner, strlen(banner); / XXX: step 5, munmap(); /int munmap(void *start, size_t length); pause(); /close(fd); return 0;/ read.c#include #include #include #include #include #include #include #include #include #define MAPPED_FILENAME/tmp/test.mmap.1#define BUFFER_SIZE1024int main(int argc, char *argv) int fd; if (argc 2) fprintf(stdout, Usage: %s n, argv0); exit(1); / XXX: step 1, open file, get a fd /int open(const char *pathname, int flags, mode_t mode); if (fd = open(argv1, O_RDWR) 0) fprintf(stderr, Error: open file failed: (errno = %d)%sn, errno, strerror(errno); exit(1); #if 0 off_t offset; offset = 1024; / XXX: step 2, create a hole file /off_t lseek(int fildes, off_t offset, int whence); if (lseek(fd, offset, SEEK_SET) = (off_t) - 1) fprintf(stderr, lseek() failed: %sn, strerror(errno); /FIXME: unlink the file close(fd); exit(1); ssize_t n; /ssize_t write(int fd, const void *buf, size_t count); if (n = write(fd, , 1) 0) fprintf(stderr, write() failed: %sn, strerror(errno); exit(1); #endif /* * On success, mmap returns a pointer to the mapped area. On error, the value MAP_FAILED (that is, (void*) -1) is returned, and errno is set appropriately. On success, munmap returns 0, on failure -1, and errno is set (probably to EINVAL). */* PROT_EXEC Pages may be executed. PROT_READ Pages may be read. PROT_WRITE Pages may be written. PROT_NONE Pages may not be accessed.*/ void *p; / XXX: step 3, mmap(), get a pointer /void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); if (p = mmap(NULL, 1024, PROT_WRITE, MAP_SHARED, fd, 0) = MAP_FAILED) fprintf(stderr, mmap() failed: %sn, strerror(errno); close(fd); exit(1); close(fd); fprintf(stdout, mapped file to memory, size = %dn, 1024); char bufferBUFFER_SIZE; / XXX: step 4, read/write on shared memory /void *memcpy(void *dest, const void *src, size_t n); memcpy(buffer, p+256, 32); fprintf(stdout, %sn, buffer); / XXX: step 5, munmap(); /int munmap(void *start, size_t length); /close(fd); return 0;5.6用消息队列编写一个客户端服务器通信的程序【实验目的】通过此实验,学员可以熟悉消息队列的概念,并能够用消息队列编写一个客户端服务器通信的程序。【实验原理】本实验需要用消息队列设计一个简易的双人聊天程序(一个服务器,两个客户端)。消息队列重点在于消息类型的匹配,客户端和服务端的“通信协议”的设计。设计思想如下:服务器端:接受客户端发来的任何信息,并根据其消息类型,转发给对应的客户端。同时,检测是否有退出标志,有则给所有的客户端发送退出标志,等待10s后,确定客户端都退出后,删除消息队列,释放空间,并退出。客户端:A和B,A给B发送信息,先发给服务器,由服务器根据自定义协议转发该消息给B。同时B接受到消息后,经由服务器给A一个回执信息,以此形成简易的聊天模式。【实验方法】编写服务器端程序:#define KEY_MSG 0x101 /使用共有的IPC key#define MSGSIZE 128#include #include #include #include #include main() int msgid; struct msgbuf /定义消息结构体:消息类型和消息数据 long mtype; char mtext128; buf1, buf2; msgid = msgget( KEY_MSG, IPC_CREAT|0666 ); while( 1 ) /无限循环,退出标志则会break msgrcv( msgid, &buf1, MSGSIZE, 1L, 0 ); /接受客户端1的消息printf( Receive client1 message: %sn, buf1.mtext ); /打印收到的消息if( buf1.mtext0 = x | buf1.mtext0 = X ) /若是退出标志,则给2个客户端都发退出信息 strcpy( buf1.mtext, x ); buf1.mtype = 3L; msgsnd( msgid, &buf1, MSGSIZE, 0 ); buf1.mtype = 4L; msgsnd( msgid, &buf1, MSGSIZE, 0 ); break; buf1.mtype = 4L;msgsnd( msgid, &buf1, MSGSIZE, 0 ); /将客户端1的消息转发给客户端2 msgrcv( msgid, &buf2, MSGSIZE, 2L, 0 ); /接受客户端2的消息printf( Receive client2 message: %sn, buf2.mtext ); /打印收到的消息if( buf2.mtext0 = x | buf2.mtext0 = X )/若是退出标志,则给2个客户端发退出信息 strcpy( buf2.mtext, x ); buf2.mtype = 3L; msgsnd( msgid, &buf2, MSGSIZE, 0 ); buf2.mtype = 4L; msgsnd( msgid, &buf2, MSGSIZE, 0 ); break; buf2.mtype = 3L;msgsnd( msgid, &buf2, MSGSIZE, 0 ); /将客户端2的消息转发给客户端1 sleep(5); /若退出,则先等待,以确保客户端程序退出 msgctl( msgid, IPC_RMID, NULL ); /删除消息队列,释放空间 exit(0);客户端1:#define KEY_MSG 0x101#define MSGSIZE 128#include #include #include #include #include main() int msgid; struct msgbuf long mtype; char mtext128; buf1, buf2; msgid = msgget( KEY_MSG, 0666 ); while( 1 ) printf( input the msg to client2: ); gets( buf1.mtext ); buf1.mtype = 1L; msgsnd( msgid, &buf1, MSGSIZE, 0 ); /客户端1获取消息并发往服务器sleep(1); /等待一秒,以确保客户端2已经收到并发了回执 msgrcv( msgid, &buf2, MSGSIZE, 3L, 0 ); /准备从客户端2获取回执消息 if( buf2.mtext0 = x | buf2.mtext0 = X ) printf( client1 will quit!n ); break; p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论