赞
踩
目录
pid_t getpid(); 获得调用该方法的当前进程id号(无参)
pid_t getppid(); 获得当前调用该方法的父进程进程id号(无参)
注意:每个进程都有其父进程!!(父进程的父进程~命令解释器bash)
(1)进程号为2346的为父进程的父进程,为命令解释器bash(当前最好用的命令解释器),用户通过命令解释器bash和系统(内核)交互。
具体操作:bash在执行可执行程序./main2时,会将自己fork()复制一份得到子bash,再将子bash进行exec()替换为可执行程序main2后再运行。
终端中执行的任何命令:其父进程均为bash。
(2)对于在父进程中fork()之前定义的变量n,其在父进程、子进程中地址(逻辑地址:逻辑地址/页面大小=页号 + 逻辑地址%页面大小=页内偏移量)相同,但对应于具体两个进程各自的页表对应物理块号不同(物理地址不同),因此值不同。
解释:打印出的n的地址为逻辑地址!!!对于逻辑地址,父进程与fork()复制得来的子进程相同,而物理地址不相同! 若是同一个进程中,逻辑地址相同则物理地址相同,但现在为两个进程(无可比性),其真实的物理地址在不同空间。
复制后的子进程从fork()返回值带回后处执行。
附加:若变为printf("A"); 去掉 \n 一定会输出>6个A且为偶数个。由于输出的A会先放在缓冲区,父进程fork()复制产生子进程时是连同缓冲区(内存)一起复制的,故会将未输出的A一同复制,到结束进程时刷缓冲区一并输出。
当父进程比子进程结束早时,还未结束的子进程叫做孤儿进程。按照约定所有没有了父进程的子进程都需要被某个特定的进程(init pid=1的进程收养,现在很多系统规定不再是1号进程,如下图为id号=1353的进程收养孤儿进程)收养。
当子进程先结束,父进程没有获取子进程的退出码时,子进程变为僵死进程<defunct>。
PCB会被串成一个双向链表,当子进程结束(如exit(0) //退出码为0)时,需要释放掉为其开辟的内存空间,同时其PCB需要被删除。但在这之前,子进程的PCB会接收其返回的退出码0,此时父进程要通过wait()获取子进程返回的退出码来了解子进程的状态:是否正常结束。故子进程的PCB需要保留到父进程结束后才可以删。若父进程先结束 子进程会被收养,则子进程就要把其退出码返回给收养进程。
要是想在后台看到僵死进程<defunct>,可以令子进程先结束,父进程不通过wait()保护子进程的结束,且执行程序时放到后台(./main&),这样就可以直接ps查看。
wait()函数返回值为捕获到的子进程的pid,同时传参变量地址将退出码写入变量,调用WEXITSTATUS()函数获取退出码。
起初父进程未被打印,由于wait()处阻塞,父进程需要等待子进程结束获取退出码并执行。
为了提高fork()的效率,减少fork()的实际开销。采用写时拷贝技术:内核并不复制整个父进程的地址空间,而是让父进程与子进程共享一个拷贝,只有在需要写入时数据才被复制(资源的复制只有在需要写入时才进行),在这之前均为只读模式。这种技术使地址空间上页的拷贝被推迟到实际发生写入的时候。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。