个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创Linux基础-进程的超详细讲解(2)_进程的创建与状态
收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌
目录
1. 通过系统调用创建进程-fork
使用fork创建子进程
fork()的返回值:
1. 在父进程中:
2. 在子进程中:
创建多进程
进程的独立性:
1. 通过系统调用创建进程-fork
使用fork创建子进程
在Linux系统下,可以使用man手册查看一个命令:
我们可以发现, fork需要包含两个头文件, 并且它的返回值是pid_t(也就是文件标识符)
那么我们可以写下这个代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
printf("hello proc : %d!, ret: %d\n", getpid(), ret);
sleep(10);
return 0;
}
输出结果如下:
我们可以发现, 由于fork()的作用, 程序在调用fork()后产生两个独立进程 (父进程和子进程). 这两个进程各自执行printf语句, 因此最终的输出将包含两行信息, 每行代表一个进程的输出.
根据程序的返回值我们可以发现:
1. 父进程执行fork():
父进程的PID是14792, 当调用fork()时, 它会创建一个新的子进程在父进程中, ret的值是子进程的PID(14793), 因此打印出的内容是:
hello proc : 14792!, ret: 14793
子进程执行fork():
子进程的ret值为0, 因为在子进程中, fork()返回值是0, 因此, 子进程打印的内容是:hello proc : 14793!, ret: 0
fork()的返回值:
1. 在父进程中:
fork()返回子进程的进程ID(PID), 这个pid是一个正整数, 表示创建的子进程的唯一标识符.
父进程可以跟踪和管理子进程
2. 在子进程中:
fork()返回0, 这意味着子进程是父进程创建的, 并且它不需要关心其自身的pid.
返回0是fork()特有的行为, 以便子进程能够确认自己是新创建的进程.
所以fork 之后通常要用 if 进行分流, 如下面代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0)
{
perror("fork");
return 1;
}
else if(ret == 0)
{ //child
printf("I am child : %d!, ret: %d\n", getpid(), ret);
}
else
{ //father
printf("I am father : %d!, ret: %d\n", getpid(), ret);
}
sleep(1);
return 0;
}
创建多进程
如下方代码所示:
#include <iostream>
#include <vector>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
const int num = 10;
void SubprocessRun()
{
while(true)
{
cout << "I am Sub process, pid : " << getpid() << "ppid: " << getppid() << std::endl;
sleep(5);
}
}
int main()
{
vector<pid_t> allchild;
for(int i = 0; i < num; i++)
{
pid_t id = fork();
if(id == 0)
{
//子进程
SubprocessRun();
}
//父进程
allchild.push_back(id);
}
//父进程
cout << "我所有的孩子是 : ";
for(auto child : allchild)
{
cout << child << " ";
}
cout << endl;
sleep(10);
while(true)
{
cout << "我是父进程, pid : " << getpid() << endl;
sleep(1);
}
return 0;
}
编译完成后:
运行结果:
在这个代码中, 让子进程陷入死循环, 一直打印子进程的pid和ppid, 父进程负责计入它的子进程
fork之后谁先运行由OS调度器自主决定!
进程的独立性:
如下方代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int gval=0;
int main()
{
printf("please Enter# ");
scanf("%d", &gval);
printf("gval: %d\n", gval);
printf("I am a process, pid: %d, ppid: %d\n", getpid(), getppid());
pid_t id = fork();
if(id > 0)
{
while(1)
{
printf("我是父进程, pid: %d, ppid:%d, ret id: %d, gval: %d\n", getpid(), getppid(), id, gval);
gval+=10;
sleep(1);
}
}
else if(id == 0)
{
while(1)
{
printf("我是子进程, pid: %d, ppid:%d, ret id: %d, gval: %d\n", getpid(), getppid(), id, gval);
gval++;
sleep(1);
}
}
(void)id;
printf("I am a 分支! pid: %d, ppid: %d\n", getpid(), getppid());
sleep(1);
}
运行结果:
可以从上面的结果得出:
1. 独立的地址空间
每个进程都有自己的地址空间, 在fork()调用之后, 父进程和子进程的内存是独立的, 虽然代码开始时共享了全局变量gval的初始值, 但一旦它们各自开始执行并修改gval, 每个进程的gval实际上是独立的, 互不影响的
2. 数据的独立性
在这个程序中, 父进程和子进程在运行时会对gval进行不同的增量操作, 父进程将其增加到10, 子进程将其增加到1, 这说明, 尽管它们一开始有相同的gval值, 但随着程序的运行, 它们的gval值将会分别发生变化, 而不在互相影响.
3. 运行状态的独立性:
父进程和子进程可以在不同的速度和时间点运行, 父进程的运行不会影响子进程(反之亦然)
总结: 进程具有很强的独立性! 多个进程之间, 运行时, 互不影响, 即便是父子, 数据各自私有一份~