Linux子进程创建
来源:互联网 发布:贪心算法实例 编辑:程序博客网 时间:2024/05/16 04:56
最近在学操作系统,新学到了一些知识,记在下面。
以下是相关源代码:
#include"sys/types.h"#include"sys/file.h"#include"unistd.h"#include"string.h"#include"stdlib.h"#include"stdio.h"#include"wait.h"char r_buf[4]; //read bufferchar w_buf[4]; //write bufferint pipe_fd[2];pid_t pid1,pid2,pid3,pid4;int producer(int id);int consumer(int id);int main(int argc,int**argv){ if(pipe(pipe_fd)<0){ printf("pipe create error\n"); exit(-1); } else{ printf("pipe is created successfully\n"); if((pid1=fork())==0){ producer(1); printf("child pid%d\n",getpid()); } else if(pid1>0){ printf("parent pid%d,children pid%d\n",getpid(),pid1); } printf("after fork() 1\n"); if((pid2=fork())==0){ producer(2); printf("child pid%d\n",getpid()); } else if(pid2>0){ printf("parent pid%d,children pid%d\n",getpid(),pid2); } printf("after fork() 2\n"); if((pid3=fork())==0){ consumer(1); printf("child pid%d\n",getpid()); } else if(pid3>0){ printf("parent pid%d,children pid%d\n",getpid(),pid3); } printf("after fork() 3\n"); if((pid4=fork())==0){ consumer(2); printf("child pid%d\n",getpid()); } else if(pid4>0){ printf("parent pid%d,children pid%d\n",getpid(),pid4); } printf("after fork() 4\n"); } close(pipe_fd[0]); // 关闭管道, close(pipe_fd[1]); // 否则读者或写者永久等待 int i,pid,status; // 等待子进程退出 for(i=0;i<4;i++){ pid = wait(&status); printf("pid%d status %d\n",pid,WEXITSTATUS(status)); } exit(0); }int producer(int id){ printf("producer%d is running!\n",id); close(pipe_fd[0]); // 半双工写,关闭读 int i; for(i = 0;i<10;i++){ sleep(1); // other producer if(id==1) strcpy(w_buf,"aaa\0"); else strcpy(w_buf,"bbb\0"); if(write(pipe_fd[1],w_buf,4)==-1) printf("write to pipe error\n"); } close(pipe_fd[1]); printf("producer%d is over\n",id); exit(id);}int consumer(int id){ close(pipe_fd[1]); // 半双工读,关闭写 printf("consumer%d is running\n",id); if(id==1) strcpy(w_buf,"ccc\0"); else strcpy(w_buf,"ddd\0"); while(1){ sleep(1); // other consumer strcpy(r_buf,"eee\0"); if(read(pipe_fd[0],r_buf,4)==0) break; printf("consumer%d get %s,while the w_buf is %s\n",id,r_buf,w_buf); } close(pipe_fd[0]); printf("consumer%d is over!\n",id); exit(id);}
在以上的程序中,主要是为了测试子进程的创建和进程间的通信,接下来对各个相关点进行分析:
1.fork
pid = fork().
fork() 在头文件unistd.h中。如果创建成功,创建一个新进程并返回新进程的进程ID(给父进程(大于0))和0(给新进程);如果不成功,返回-1给父进程。参数无,返回类型为pid_t。
父进程
if((pid1=fork())==0){ producer(1); printf("child pid%d\n",getpid()); } else if(pid1>0){ printf("parent pid%d,children pid%d\n",getpid(),pid1); } printf("after fork() 1\n");if((pid2=fork())==0){ producer(2); printf("child pid%d\n",getpid()); }
由于子进程是父进程的一个副本,它们的程序计数器具有相同的值,所以在调用fork()之后两个进程都进入if判断,根据判断的结果执行相应的代码。如果pid1的值为0,那么正在执行的进程一定是子进程,该进程调用producer函数;如果pid的值大于0,那么正在执行的进程一定是父进程,该父进程执行printf语句。值得注意的是,在执行结果中,以上片段的最后一条printf语句只被执行了一次,原因在于子进程在producer函数中执行了exit函数,这导致子进程直接退出而不是返回原来的调用点,如果把exit换成return,那么子进程将执行在 “producer(1);” 语句后的代码。正是这个原因,使得第2个fork()没被子进程执行,否则产生的将不止4个进程,而是16个进程(总共有4个fork()调用)。
2.wait
pid = wait(&status_ptr).
wait()函数在头文件wait.h中。返回下一个子进程的进程ID并退出,退出状态写入由status_ptr指向的内存地址。参数int* status_ptr,返回类型pid_t。
int i,pid,status; // 等待子进程退出 for(i=0;i<4;i++){ pid = wait(&status); printf("pid%d status %d\n",pid,WEXITSTATUS(status)); }
wait函数返回退出的子进程的ID或0(如果不存在任何子进程),在以上程序片段中,它被保存在pid中。wait 函数在参数status(int 类型)中存储了进程的退出状态,包括退出代码;使用宏调用WEIXTSTATUS(status)可以从变量status中提取退出代码。如果调用进程中不存在任何子进程,退出代码显示出现错误。
3.pipe
pipe(filedes).
pipe函数在头文件unistd.h中。如果成功,创建新管道并返回0,读和写文件描述符写入数组参数中;如果失败返回-1。参数int filedes[2],返回类型int。
int pipe_fd[2];. . .f(pipe(pipe_fd)<0){ printf("pipe create error\n"); exit(-1); } else{ printf("pipe is created successfully\n"); . . . }
已知的进程通信所用的最老的形式为管道(pipe),它由两个文件描述符构成,一个为读打开,另一个为写打开。共有两种类型的管道:半双工和全双工,半双工管道只能向一个方向发送信息(->),而全双工管道可以向两个方向发送消息(<->)。在以上程序片段中,如果管道创建成功,将返回两个文件描述符到数组pip_fd中(pip_fd[0]为读描述符)。因为并非所有的操作系统都支持全双工管道,为保证信息只能向一个方向发送,即将从管道读数据的进程应该关闭写文件描述符,而即将向管道写数据的进程应该关闭读文件描述符。使用文件函数close可以关闭管道文件描述符,使用文件write函数可以向管道写文件描述符中写入信息,使用文件read函数可以从管道读文件描述符中读信息。
如果进程必须能够向两个方向发送信息,全双工管道可以用两个半双工管道模拟,其中的一个半双工管道用作读,另一个用作写。
以上便是此次总结,有些地方也许认识得还不够全面,欢迎各位指教。
- linux 创建子进程
- Linux子进程创建
- windows、linux创建子进程
- windows、linux创建子进程
- Linux fork()创建子进程
- linux fork创建子进程
- Linux多进程 -- 创建子进程
- Linux 调用fork()创建两个子进程
- linux之fork,vfork创建子进程
- 【操作系统】linux创建子进程--fork()方法
- Linux创建子进程的具体过程
- Linux学习之创建子进程
- 【操作系统】linux创建子进程--fork()方法
- LInux 子进程创建函数fork简介
- Linux 创建子进程函数 --- fork
- linux进程编程:子进程创建及执行函数简介
- Linux间的进程通信;以及子进程的创建
- Linux父进程创建子进程的方法,监控子进程的结束
- 0级,1级,2级监听
- 详解设计模式——适配器模式
- 死锁
- iOS--脚本配置Xcode Project(打包)
- Resource is out of sync with the file system的解决办法
- Linux子进程创建
- java线程学习之Condition
- python开发虚拟环境搭建步骤
- Android 消息机制
- 详解设计模式——外观模式
- [Qt]Qt--拖拽实现
- xcodebuild和xcrun实现自动打包iOS应用程序
- BZOJ 1588 营业额统计(TREAP)
- ffplay音视频同步分析(一)