本周操作系统实验课要求写几个关于Linux下进程通信的小程序。
实验要求如下:
第一个程序已在前篇文章中贴出,本文给出后两个。
使用共享存储区通信:
memserve.c:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #define Key 3000 int main(void) { int x, shmid; int *shmptr; if((shmid=shmget(Key, sizeof(int), IPC_CREAT|0666)) < 0) printf("shmget error"), exit(1); if((shmptr=(int *)shmat(shmid, 0, 0)) == (int *)-1) printf("shmat error"), exit(1); printf("Serve start: \n"); while(1) { scanf("%d",shmptr); int i=*shmptr; while(i==*shmptr); printf("Client number: %d\n",*shmptr); } }
memclient.c:
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #define Key 3000 int main(void) { int x, shmid; int *shmptr; if((shmid=shmget(Key, sizeof(int), 0666)) < 0) printf("shmget error"), exit(1); if((shmptr=(int *)shmat(shmid, 0, 0)) == (int *)-1) //第二个参数指定引入位置,0表示由内核决定引入位置 printf("shmat error"), exit(1); printf("Client start:\n"); while(1) { scanf("%d",shmptr); int i=*shmptr; while(i==*shmptr); printf("Serve number: %d\n",*shmptr); } }
先运行semserve.c,后运行semclient.c。以上程序虽然已经可以做到在服务器和客户端间轮流修改共享存储区值并显示结果,但是在启动服务器和客户端的时候必须先输入两个不相等的值!这只不过是非常简单的一种处理方式,希望高手给出更好的方式哈!(百度之后发现有人通过对 share memory做P()V()操作来解决这个问题!我自己还想了一种方式:可以通过创建一个struct Memory{ id,value} 。id中存放进程的标识,然后在后面while()中输出时,做判断。是对方的id则输出。)
运行结果如下:
管道通信:
三写一读方式:(三个写进程分别将要写入的三个参数写入管道,一个读进程负责读出)
#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { int pipefd[2]; pid_t cpid;//Linux下的进程号类型。宏定义 unsigned int char buf,buf1=' '; if (argc != 4) { printf("Need four arguments."); exit(EXIT_FAILURE); } if (pipe(pipefd) == -1) { //如果管道创建失败则退出 perror("pipe"); exit(EXIT_FAILURE); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { close(pipefd[1]); //关闭写管道 while (read(pipefd[0], &buf, 1) > 0) write(STDOUT_FILENO, &buf, 1); write(STDOUT_FILENO, "\n", 1); close(pipefd[0]); _exit(EXIT_SUCCESS); } else { close(pipefd[0]); //关闭读管道 write(pipefd[1], argv[1], strlen(argv[1]));//strlen() 计算argc[1]字节数 write(pipefd[1],&buf1,1); cpid = fork(); if (cpid == -1) { printf("Faliled"); exit(EXIT_FAILURE); } if(cpid==0) { write(pipefd[1], argv[2], strlen(argv[2])); write(pipefd[1],&buf1,1);//第二个参数必须是地址! } else { wait(NULL); write(pipefd[1], argv[3], strlen(argv[3])); write(pipefd[1],&buf1,1); } close(pipefd[1]); wait(NULL); exit(EXIT_SUCCESS); } }
运行结果如下:
两写两读:
#include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { int pipefd[2]; pid_t cpid;//Linux下的进程号类型。宏定义 unsigned int char buf,buf1=' '; if (argc != 3) { printf("Need three arguments."); exit(EXIT_FAILURE); } if (pipe(pipefd) == -1) { //如果管道创建失败则退出 perror("pipe"); exit(EXIT_FAILURE); } while((cpid=fork())==-1);//创建失败则循环继续创建 if (cpid == 0) { //写进程 close(pipefd[0]); write(pipefd[1], argv[1], strlen(argv[1]));//strlen() 计算argc[1]字节数 write(pipefd[1],&buf1,1); close(pipefd[1]); exit(EXIT_SUCCESS); } else { wait(NULL); //子进程的结束状态由参数返回。NULL表明不在意结束状态 write(pipefd[1], argv[2], strlen(argv[2]));//strlen() 计算argc[1]字节数 write(pipefd[1],&buf1,1); close(pipefd[1]); while((cpid=fork())==-1); if(cpid==0) { while (read(pipefd[0], &buf, 1) > 0) { if(buf==' ') break; write(STDOUT_FILENO, &buf, 1); } write(STDOUT_FILENO, "\n", 1); close(pipefd[0]); exit(EXIT_SUCCESS); } else { wait(NULL); while (read(pipefd[0], &buf, 1) > 0) write(STDOUT_FILENO, &buf, 1); write(STDOUT_FILENO, "\n", 1); close(pipefd[0]); } exit(EXIT_SUCCESS); } }
结果如下: