目录
为了实现进程间通信,使得两个不同的进程间可以交换数据,操作系统必须提供两个进程可以同时访问的内存空间;
为了完成进程间通信,需要创建管道(pipe);管道并非属于进程的资源,而是属于操作系统;
- #include
- int pipe(int filedes[2]);
- // 成功时返回0,失败时返回-1
- // filedes[0] 通过管道接收数据时使用的文件描述符,即管道出口
- // filedes[1] 通过管道传输数据时使用的文件描述符,即管道入口
子进程从管道入口写数据,父进程从管道出口读数据;
- // gcc pipe1.c -o pipe
- // ./pipe
-
- #include
- #include
- #define BUF_SIZE 30
-
- int main(int argc, char *argv[]){
- int fds[2];
- char str[] = "Who are you?";
- char buf[BUF_SIZE];
- __pid_t pid;
-
- pipe(fds); // 创建管道
- pid = fork();
- if(pid == 0){ // 子进程执行区域
- write(fds[1], str, sizeof(str)); // 向管道入口写数据
- }
- else{ // 父进程执行区域
- read(fds[0], buf, BUF_SIZE); // 向管道出口读数据
- puts(buf);
- }
- return 0;
- }

利用一个管道实现父进程与子进程的双向通信;
- // gcc pipe2.c -o pipe2
- // ./pipe2
-
- #include
- #include
- #define BUF_SIZE 30
-
- int main(int argc, char *argv[]){
- int fds[2];
- char str1[] = "Who are you?";
- char str2[] = "Thank you for your message";
- char buf[BUF_SIZE];
- __pid_t pid;
-
- pipe(fds); // 创建管道
- pid = fork();
- if(pid == 0){ // 子进程执行区域
- write(fds[1], str1, sizeof(str1));
- sleep(2); // sleep的作用是防止子线程写的数据被子线程自身读取了,导致父进程一直等待
- read(fds[0], buf, BUF_SIZE);
- printf("Child proc output: %s \n", buf);
- }
- else{ // 父进程执行区域
- read(fds[0], buf, BUF_SIZE);
- printf("Parent proc output: %s \n", buf);
- write(fds[1], str2, sizeof(str2));
- sleep(3);
- }
- return 0;
- }

利用两个管道实现父进程与子进程的双向通信,其中收发数据在不同的管道上进行;
- // gcc pipe3.c -o pipe3
- // ./pipe3
-
- #include
- #include
- #define BUF_SIZE 30
-
- int main(int argc, char *argv[]){
- int fds1[2], fds2[2];
- char str1[] = "Who are you?";
- char str2[] = "Thank you for your message";
- char buf[BUF_SIZE];
- __pid_t pid;
-
- pipe(fds1), pipe(fds2); // 创建管道
- pid = fork();
- if(pid == 0){ // 子进程执行区域
- write(fds1[1], str1, sizeof(str1)); // 通过管道1写数据
- read(fds2[0], buf, BUF_SIZE); // 通过管道2读数据
- printf("Child proc output: %s \n", buf);
- }
- else{ // 父进程执行区域
- read(fds1[0], buf, BUF_SIZE); // 通过管道1读数据
- printf("Parent proc output: %s \n", buf);
- write(fds2[1], str2, sizeof(str2)); // 通过管道2写数据
- sleep(3);
- }
- return 0;
- }

服务器端创建两个进程,一个进程负责与客户端进行通信,将客户端发来的数据通过管道入口写到管道中;另一个进程负责从管道出口中读取数据,并把读取的数据保存在文件中;
具体可运行代码参考:Chapter11
- // gcc echo_storeserv.c -o echo_storeserv
- // ./echo_storeserv 9190
-
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define BUF_SIZE 30
-
- void error_handling(char *message){
- fputs(message, stderr);
- fputc('\n', stderr);
- exit(1);
- }
-
- void read_childproc(int sig){
- __pid_t pid;
- int status;
- pid = waitpid(-1, &status, WNOHANG);
- printf("remove proc id: %d \n", pid);
- }
-
- int main(int argc, char* argv[]){
- int serv_sock, clnt_sock;
- struct sockaddr_in serv_adr, clnt_adr;
- int fds[2];
-
- __pid_t pid;
- struct sigaction act; // 信号
- socklen_t adr_sz;
- int str_len, state;
- char buf[BUF_SIZE];
- if(argc != 2){
- printf("Usage : %s
\n" , argv[0]); - exit(1);
- }
-
- act.sa_handler = read_childproc; //设置信号处理函数
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- state = sigaction(SIGCHLD, &act, 0);
-
- serv_sock = socket(PF_INET, SOCK_STREAM, 0); // 创建 tcp socket
- memset(&serv_adr, 0, sizeof(serv_adr));
- serv_adr.sin_family = AF_INET;
- serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_adr.sin_port = htons(atoi(argv[1]));
-
- if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr)) == -1){
- error_handling("bind() error");
- }
- if(listen(serv_sock, 5) == -1){
- error_handling("listen() error");
- }
-
- pipe(fds);
- pid = fork();
- if(pid == 0){ // 子进程执行区域
- FILE* fp = fopen("echomsg.txt", "wt");
- char msgbuf[BUF_SIZE];
- int i, len;
-
- for(i = 0; i < 10; i++){
- len = read(fds[0], msgbuf, BUF_SIZE);
- fwrite((void*)msgbuf, 1, len, fp);
- }
- fclose(fp);
- return 0;
- }
- while(1){
- adr_sz = sizeof(clnt_adr);
- clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_adr, &adr_sz);
- if(clnt_sock == -1){
- continue;
- }
- else{
- puts("new client connected...");
- }
-
- pid = fork();
- if(pid == 0){
- close(serv_sock);
- while((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0){
- write(clnt_sock, buf, str_len);
- write(fds[1], buf, str_len);
- }
- close(clnt_sock);
- puts("client disconnected...");
- return 0;
- }
- else{
- close(clnt_sock);
- }
- }
- close(serv_sock);
- return 0;
-
- }
