建站公司推荐首推万维科技,WordPress签到打卡,php网站开发怎么接私活,集团网站 备案相信大家在初学进程时#xff0c;对fork函数创建进程一定会有很多的困惑#xff0c;比如#xff1a;
1.fork做了什么事情?? 2.为什么fork函数会有两个返回值?3.为什么fork的两个返回值#xff0c;会给父进程谅回子进程pid#xff0c;给子进程返回0?4.fork之后:父子进… 相信大家在初学进程时对fork函数创建进程一定会有很多的困惑比如
1.fork做了什么事情?? 2.为什么fork函数会有两个返回值?3.为什么fork的两个返回值会给父进程谅回子进程pid给子进程返回0?4.fork之后:父子进程谁先运行??5.如何理解同一个变量会有不同的值??
本篇文章将来仔细回答一下这些问题。
目录
1.如何查看进程
2. 通过系统调用创建进程-fork
2.1 初识fork
2.2 fork原理 1.如何查看进程
1.1 进程的信息可以通过 /proc 系统文件夹查看
通过ls指令来查看所有的进程proc是动态目录结构用来存放所有的进程目录的名称就是用进程的id命名的。 1.2 进程信息同样可以使用ps(process status)工具来获取
进程idPID通过getpid 系统调用获得父进程idPPID通过getppid 系统调用获得 #includestdio.h#includesys/types.h#includeunistd.hint main(){while(1){printf(I am a process! myid:%d parentid:%d\n,getpid(),getppid()) ;sleep(1);}return 0;}我们可以使用shell再开一个窗口登录一次进行查看。 aux 是 ps 命令的选项之一表示显示所有用户的所有进程通过查询可以看到你自己 ./ 启动的进程最后一个进程是当前的grep的查找进程。
关于当前工作目录
我们在C语言学习文件操作是会提到当前目录我们以 w 方式读取文件时如果文件不存在那么文件会在当前工作目录cwd下创建。那么一个进程是如何找到当前目录的呢
我们让下面代码运行起来 1 #includestdio.h2 #includesys/types.h3 #includeunistd.h4 int main()5 {6 //更改当前工作目录7 chdir(./wdz);//没有这个目录不会更改我这里是创建好了这个目录 8 9 // cwd/hello.txt 10 FILE* file fopen(hello.txt,w);//文件不存在会在当前工作目录下创建11 if(fileNULL)12 {13 return 1;14 }15 fclose(file);16 17 18 while(1)19 {20 printf(I am a process! myid:%d parentid:%d\n,getpid(),getppid());21 sleep(1);22 }23 return 0;24 } 这里通过修改当前目录已经对将文件创建在更改的目录下 可以发现 默认情况下进程所处的目录就是当前工作目录 一个进程可以找到自己的可执行程序每一个进程都有自己的工作目录 2. 通过系统调用创建进程-fork
2.1 初识fork
首先使用fork创建一个进程 #includestdio.h#includeunistd.h#includesys/types.hint main(){printf(我是一个父进程我的pid:%d\n,getpid());//创建一个子进程 pid_t id fork();//fork之前只有父进程会执行fork之前的代码fork之后父子进程都要执行后面的代码while(1){printf(我是一个进程,pid:%d,ppid%d,fork return:%d\n,getpid(),getppid(),id);//这个printf函数在代码这里只调用一次但在运行时调用了两次sleep(1);//for test}return 0;}运行结果 看到这里大家的疑惑就出来了 目前可以发现只有父进程执行fork之前的代码fork之后父子进程都要执行后续的代码! 一个函数竟然会有两个返回值???fork成功的时候会有两个不同的返回值,给子进程返回0; 给父进程返回子进程的pid fork代码的一般写法: 1.我们为什么要创建子进程 我们想让子进程协作父进程完成一些工作这些工作是单进程解决不了的 2.我们创建子进程是为了让子进程和父进程做一样的事情吗 我们创建子进程就是为了让子进程和父进程做不一样的事情执行不一样的代码 3. 应该如何保证父子进程做不一样的事情呢? 可以通过判断fork的返回值判断谁是父谁是子然后让他们执行不同的代码片段!! 使用 if 对父子进程分流
#includestdio.h
#includeunistd.h
#includesys/types.hint main()
{printf(我是一个父进程我的pid:%d\n,getpid());//创建一个子进程 //bash也是用C语言写的命令行启动的进程都是bash的子进程所以bash源代码中创建子进程也是用的forkpid_t id fork(); //fork()之后用if进行分流 if(id0) return 1; //进程创建失败 else if(id 0) { //子进程 while(1) { printf(我是子进程,pid:%d,ppid%d,ret:%d,正在执行下载\n,getpid(),getppid(),id); sleep(1);//for test } } else { //父进程 while(1) { printf(我是父进程,pid:%d,ppid%d,ret:%d,正在执行播放任务\n,getpid(),getppid(),id); sleep(1);//for test }}return 0;
}
执行结果 可以发现通过 if 对fork函数返回值进行判断实现了父子进程可以执行不同的任务。
2.2 fork原理
对于上面的现象我们来解答一下疑惑
1.fork做了什么事情?? 2.为什么fork函数会有两个返回值?3.为什么fork的两个返回值会给父进程谅回子进程pid给子进程返回0?4.fork之后:父子进程谁先运行??5.如何理解同一个变量会有不同的值?? 1. fork做了什么事情?? 用于创建一个进程在内核中操作系统重新为其申请了一个PCB并使用父进程的PCB进行初始化且子进程与父进程同时指向相同的代码。所以fork之前的代码子进程也是可以看到的。 那为什么子进程不从头开始执行呢? 因为有程序计数器pc会使代码一句一句执行子进程在创建时和继承父进程的pc。所以说也会继续向下执行。 2.为什么fork函数会有两个返回值? 首先fork是一个函数如果一个函数return时说明一个函数的核心工作已经做完。我们知道fork之后代码会共享所以是fork函数做完核心工作后就会共享return也会父子进程共享所以会有两个返回值。 3.为什么fork的两个返回值会给父进程谅回子进程pid给子进程返回0? 因为一个父进程可以有多个子进程父进程信息中只有pid 和 ppid为了唯一确定子进程所以返回子进程的pid而子进程中由于有父进程ppid所以返回0可以用来判断。 4.fork之后:父子进程谁先运行?? 不确定。创建完成子进程只是一个开始。创建完成子进程之后系统的其他进程父进程和子进程接下来要被调度执行的当父子进程的PCB都被创建并在运行队列中排队的时候哪一个进程的PCB先被选择调度那个进程就先运行由操作系统自主决定由各自PCB中的调度信息(时间片优先级等)调度器算法共同决定。 5.如何理解同一个变量会有不同的值?? 进程的独立性首先是表现在有各自的PCB进行之间不会互相影响代码本身是只读的不会影响但是数据父子是会修改的所以代码共享但是数据各个进程必须想办法各自私有一份 这个怎么做到的通过写时拷贝。这样做的好处就是不用将所有的数据都进行拷贝当数据需要修改时才做拷贝可以提高效率。 本篇结束