对一些函数和知识的解释
-
getpid():返回当前进程的PID(进程编号)
-
pid_t C语言重新定义的数据类型(其实就是int,换了一个名字)用来存储进程的PID。pid_t定义在sys/types.h头文件中
-
fork()函数:用于创建一个新进程作为当前进行的子进程。
如果成功创建⼦进程,对于⽗⼦进程fork会返回不同的值,对于父进程将返回子进程的PID,而如果是子进程将返回0。
如果进程创建失败,将返回-1 -
**pause():将当前进程处于暂停状态,使用ctrl+c可以退出暂停
-
命令:ps-al可以列出当前运行进程的详细信息
1.通过代码创建一个进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
// getpid()函数返回当前进程的ID号
printf("Before fork Process id:%d\n", getpid());
printf("After fork Process id:%d\n", getpid());
pause();
return 0;
}
- 执行代码
我们可以看到当前已经存在一个PID=2455的进程 - 此时我们执行pa-al进一步验证
可以从上面列出的进程信息可以发现PID=2425的进行已经存在
2. 通过fork()函数创建⼦进程
我们使用fork创建一个当前进程的子进程,从新运行
从上面的运行结果我们可以看出,after的printf执行了2遍。但是输出了不同给Pid号
- 执行ps -al命令查看此时的进程目录
图中2583的PPID是2582,PPID表示的是当前将进程的父进程的PID,所有可以知道关于Afer的printf执行2遍是父进程和子进程各自执行了1遍
为什么前面的after哪个会执行2遍(父进程执行一遍,子进程执行一遍)
fork在创建一个子进程时,会将父进程在内存中的数据原模原样复制一份作为子进程的内存。子进程被创建后会和父进程一起从fork处往后并发执行
3. 通过cid区分⽗⼦进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid; //child pid
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){ // 该分⽀是⼦进程执⾏的代码
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());
for(int i = 0; i < 3; i++){
printf("hello\n");
}
}else{ // 该分⽀是⽗进程执⾏的代码
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 3; i++){
printf("world\n");
}
wait(NULL);
}
return 0;
}
从上面的执行顺序可以发现是父进程先执行,然后子进程再执行。没有体会到父子进程是交替并发执行的
- 通过增加for循环的次数来该进程程序
从上面的一段运行结果来看,他们确实是并发执行的
4.理解父子进程拥有独立的运行空间
前面在创建子进程的时候就是,父进程将自己的在内存中的数据复制出一份给子进程作为子进程在内存中的数据。意思是在fork之后父子进程拥有了完全独立并且一摸一样的内存数据
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char const *argv[])
{
pid_t cid; //child pid
int value=100;//define value
printf("Before fork Process id:%d\n", getpid());
cid = fork();
if (cid == 0){ // 该分⽀是⼦进程执⾏的代码
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid());
for(int i = 0; i < 3; i++){
printf("hello(%d)\n",value--);
}
}else{ // 该分⽀是⽗进程执⾏的代码
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 3; i++){
printf("world(%d)\n",value++);
}
wait(NULL);
}
return 0;
}
我们先定义了一个变量value=100。这个value将作为进程的组成部分(将会存储在栈中)存储在内存中。通过fork时,value=100也将复制给子进程
从运行的结果可以看出。父子进程的value可以独立的变化。可以看出2个进程的内存数据是独立的,而不是公用的
理解孤儿进程
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
21
22
23
24
25
26
27
28
29
30
31
32
int main(int argc, char const *argv[])
{
pid_t cid; //child pid
printf("Before fork Process id:%d\n", getpid());
int value = 100;
cid = fork();
if (cid == 0){
printf("Child process id (my parent pid is %d):%d\n", getppid(),getpid())
for(int i = 0; i < 3; i++){
printf("hello(%d)\n",value--);
}
}else{
printf("Parent Process id: %d\n",getpid());
for(int i = 0; i < 3; i++){
printf("world(%d)\n",value++);
}
// wait(NULL); //等待⼦进程结束了再执⾏
}
// 变成了孤⼉进程,交给系统进程托管(Pid = 1)
return 0;
父进程执行wait()时将会进程等待状态,等到子进程运行完毕,才会执行。
⽗进程在⼦进程结束之前就已经执⾏完成了,此时⼦进程就变成了孤⼉进程,交给系统进程托管
(Pid = 1