先上一个多进程的简单多进程实例,此实例将在同一个程序中建立两个进程:编程
/* 程序说明: 建立两个进程,进程一执行”ls -l“操做,进程二作sleep操做 主进程阻塞等待进程1结束,再等待进程2结束,程序结束 */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t child1,child2; child1 = fork(); //进程1 if(child1 == -1){ perror("child1 creat error:"); exit(1); }else if(child1 == 0){ if(execlp("ls","ls","-l",NULL) < 0){ perror("execlp error:"); exit(1); } exit(0); } child2 = fork(); //进程2 if(child2 == -1){ perror("child2 creat error:"); exit(1); }else if(child2 == 0){ sleep(3); exit(0); } // waitpid(child1,NULL,0); 主进程 wait(0); while(waitpid(child2,NULL,WNOHANG)==0){ printf("child2 not exit\n"); sleep(1); } exit(0); }
建立多进程的时候须要注意,不要连续建立多个进程,不然上面建立的子进程将同时建立下面的进程,向下面这样:数组
child1 = fork(); child2 = fork();
经过下面代码能够看出子进程1同时也建立了进程2:安全
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t child1,child2,child_temp; child1 = fork(); child2 = fork(); if(child1 == -1){ perror("child1 creat error:"); exit(1); } if(child2 == -1){ perror("child2 creat error:"); exit(1); } if(child1 == 0){ sleep(2); // exit(0); wait(0); } if(child2 == 0){ sleep(3); exit(0); } // waitpid(child1,NULL,0); while(waitpid(child1,NULL,WNOHANG)==0){ printf("chil1 has not exit\n"); sleep(1); } while(waitpid(child2,NULL,WNOHANG)==0){ printf("child2 has not exit\n"); sleep(1); } exit(0); }
不少时候,不一样的进程之间须要交换数据,即相互通讯。而进程之间的通行方式也有多种,为了知足进程间通讯在不一样场景下的需求:管道通讯(pipe),信号(signal),信号量(semaphore),共享内存(shared memory),消息队列(message queue),套接字(socket)。socket
接下来就一一来探索。函数
管道分为无名管道和有名管道。翻译
无名管道:调试
一、基于文件描述符,只能用于具备亲缘关系的进程之间的通讯;code
二、是一种单工的通讯协议,具备固定的读断和写断;索引
三、无名管道不属于任何文件系统,而且只存在于内存中。队列
编程细解:主要使用pipe()函数,例程为一个父进程写进,子进程读取的一个进程间通讯实例。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <errno.h> #define MaxDataLen 256 #define DelayUTime 1 int main() { pid_t pid; int pipe_fd[2]; char buf[MaxDataLen]; const char data[] = "Pipe Test Program"; int real_read,real_write; memset(buf,0,sizeof(buf)); if(pipe(pipe_fd)<0) /* pipe运行机制: 函数原型:int pipe(int pipefd[2]); 描述:pipe()用于建立一个单向数据通道,能够用于进程间通讯; 使用数组pipefd返回两个文件描述符指管的两端; pipefd[0]是指读的管道。pipefd[1]是指写的管道; 数据在已写入管道而未被读取时由内核提供缓冲。 */ { perror("creat pipe failed:"); /* perror运行机制: 函数原型:void perror(const char *S); 描述:当一个系统调用失败时,它一般会返回-1并设置变量errno用于描述这个错误(这个值能够在errno.h中找到)\ perror函数会翻译这些值成为可阅读的信息。errno会在一个成功的系统调用会是库函数调用后变成undefined。 程序中存在一个全局的错误表sys_errlist[],能够被下标errno索引。 NOTES: sys_nerr & sys_errlist 在 <stdio.h> 中 SEE ALSO: err(),errno(),error(),strerror() */ exit(-1); } if((pid = fork()) == 0){ //子进程为读端 close(pipe_fd[1]); usleep(DelayUTime); if((real_read = read(pipe_fd[0],buf,MaxDataLen)) > 0){ printf("%d bytes:%s\n",real_read,buf); } close(pipe_fd[0]); exit(0); }else if(pid > 0){ //父进程为写端 close(pipe_fd[0]); if((real_write = write(pipe_fd[1],data,strlen(data))) != -1){ printf("wrote %d bytes:'%s'\n",real_write,data); } close(pipe_fd[1]); wait(0); exit(0); } }
有名管道:
一、它能够用于互不相关的两个进程间通讯;
二、在文件系统中可见,但仍是单工通讯;
三、遵循先进先出规则。
编程细解:能够先使用 mkfifo 指令在磁盘中建立一个有名管道文件,而后再程序中打开;也能够在程序中使用mkfifo()函数建立有名管道。读写依旧使用read(),write()函数。
mkfifo Linux指令: mkfifo [OPTION]... NAME... 描述:建立名为NAME的fifo文件; options: -m, --mode=MODE 设置文件权限位模式 -Z 设置SELinux安全上下文的默认类型 例:mkfifo -m 777 /tmp/temp
对于有名管道,咱们使用一个写端程序和一个读端程序来看进程通讯:
/* fifo_write.c 写端程序 */ #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> int main(int argc,char *argv[]) { int fifo_fd; char buf[] = "hello"; if((fifo_fd = open("/tmp/temp",O_WRONLY,0600)) < 0){ fifo_fd = mkfifo("/tmp/temp",0777); //如没有此管道文件,mkfifo()建立管道文件 } if(write(fifo_fd,buf,strlen(buf)) > 0){ printf("Write '%s' to FIFO\n",buf); } close(fifo_fd); exit(1); }
/* fifo_read.c 读端程序 */ #include <sys/types.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc,char *argv[]) { int fifo_fd; char buf[256]; fifo_fd = open("/tmp/temp",O_RDONLY); if(fifo_fd < 0){ perror("open temp failed:"); exit(-1); } while(1){ memset(buf,0,sizeof(buf)); if(read(fifo_fd,buf,256) > 0){ printf("Read '%s' from FIFO\n",buf); } } close(fifo_fd); exit(1); }
这个程序调试须要用到两个窗口,两个程序分开编译,先打开写程序,再打开读程序。