初识Linux · 进程(3)

发布时间 - 2025-06-20 00:00:00    点击率:

前言:

承接上文中对进程的内部属性及在操作系统层面的组织方式、系统接口调用、task_struct等方面的介绍,今天我们将从进程的相关属性出发,继续探讨进程的创建过程。

进程的创建承接上文。

上文提到,进程的创建是通过调用系统接口fork实现的,因此有时对子进程理解不深的人可能会编写如下代码:

while(1){
    printf("aaa\n");
    fork();
    printf("...\n");
}

这段代码本身并无错误,但运行时会发现打印的结果并非单一的父子进程输出。因为子进程会执行父进程的后续代码,导致子进程也会进入死循环,进而创建更多的子进程,形成指数级增长。因此第二个printf语句的输出会呈1、2、4、8的模式递增,这容易让人感到困惑。

接下来,我们来看另一个场景,编写了如下代码:

printf("I am a child process, my pid is %d\n", getpid());
printf("I am a parent process, my pid is %d\n", getppid());

运行这段代码时,你会发现pid会变化,这是正常的现象。但为什么ppid保持不变呢?这也是正常的吗?

当我们使用指令ps -xaj打开任务管理器界面时,会发现2878进程是bash(注意,2878不一定是bash,具体取决于./test,每个进程的pid都会变化)。

那么,什么是bash呢?

当我们运行:

bash会提示我们./是个目录,无法运行。

实际上,bash就是命令行解释器。我们刚才运行的./test就像是公司的实习生,而bash则是公司的boss,管理着所有的实习生(子进程)。

为什么我们要创建子进程呢?

根据前面的代码,我们知道子进程会继承父进程的后续所有代码。但我们创建子进程的目的是为了执行这些代码吗?父进程也可以执行啊,为什么要创建子进程呢?这时候,前面埋下的伏笔就起作用了。这里有一个容易让人迷惑的问题:一个函数的返回值可以返回几次?

大多数初学者可能都会回答一次,但fork的奇异之处就在这里:

当我们man fork后,在手册中查询返回值的描述时,翻译过来就是:成功创建子进程,那么子进程的Pid就会返回给父进程,0返回给子进程,失败了则返回-1给父进程。也就是说,成功时会有两个返回值,我们就可以编写如下代码:

pid_t id = fork();
if(id == 0)
{
    printf("hehehe\n");
}
else
{
    printf("hahahha\n");
}

最后的打印结果是:

按照传统C语言的逻辑,只会打印一个,但这里却颠覆了我们的代码观念。

奇怪的是,明明变量只有一个id,为什么会有两份呢?

实际上,在fork的时候,fork的实现部分,return id是代码吧?在fork的函数体内,已经创建了子进程,所以会返回两份id,因为父进程也会进入fork函数,因此有了两份id。至于为什么会有“两份”,我们先埋个伏笔。

由此得出结论,子进程的创建是为了执行不同的任务,而不是为了执行与父进程相同的工作。

那么,我们如何创建指定数量的进程呢?

如果我们采用最开始的指数级别创建方式,显然不好控制。我们可以利用fork的返回值来帮助我们创建指定数量的进程。因为创建成功时,会返回0给子进程,我们可以让这个子进程进入一个函数体中不再出来,这样就不会导致子进程创建子进程的情况:

void Run()
{
    while(1)
    {
        printf("My pid is %d, ppid is %d\n", getpid(), getppid());
        sleep(1);
    }
}

int main()
{
    for(int i = 0; i < 5; i++)
    {
        pid_t id = fork();
        if(id == 0)
        {
            Run();
            break;
        }
    }
    Run();
    return 0;
}

来看一下结果。

不出所料,我们创建了6个进程,主函数是第一个进程,后面通过for循环创建了5个子进程,且5个子进程之间没有关联。通过它们的pid我们发现5个子进程的ppid都是父进程的12607。我们大胆预测父进程的ppid 4335是bash进程,这一点我们就不验证了。

现在我们已经基本熟悉了进程的创建,那么如何查看进程的大部分信息呢?

首先引入一个问题,指令是进程吧?那么我们运行指令后,指令的工作路径在哪里呢?这个问题可能有点让人摸不着头脑,我们用文件举例,如果我们编写如下代码:

int main(){
    chdir("/home/whb/111");
    FILE *fp = fopen("log.txt", "w");
    (void)fp; // 忽略警告
    fclose(fp);
    while(1)
    {
        printf("I am a process, pid: %d\n", getpid());
        sleep(1);
    }
    return 0;
}

那么log.txt文件默认会在哪里创建呢?应该是当前代码的工作路径吧?

在VS中就像这样,同理,Linux中的进程工作时也应该有自己的工作路径,我们从哪里查看工作路径呢?

在根目录的proc中,proc是process的缩写。

此时,我们就可以看到proc中的信息了。如果我们要查看某个具体进程的信息,只需要:

同时运行其他两条指令,我们在27847父进程中可以注意以下事项:

本文首先关注两个属性,一个是cwd,一个是exe,cwd是current working directory,当前工作目录的意思,exe则记录对应进程中可执行文件的路径。

当你对某个进程进行cd操作时,发现可以cd进去,说明进程本质上就是一个个的目录,目录中记录了进程的所有信息。此时,对Linux中“一切皆文件”的理解又加深了一层!

感谢阅读!


# linux  # c语言  # 操作系统  # ai  # 为什么  # bash  # for  # Directory  # printf  # 循环  # 继承  # 接口  # 让人  # 两份  # 返回值  # 当我们  # 也会  # 是为了  # 这段  # 就可以  # 为什么会有  # 自己的 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  如何在腾讯云服务器快速搭建个人网站?  如何在Windows 2008云服务器安全搭建网站?  油猴 教程,油猴搜脚本为什么会网页无法显示?  深圳网站制作的公司有哪些,dido官方网站?  PHP 500报错的快速解决方法  Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载  如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧  进行网站优化必须要坚持的四大原则  详解jQuery停止动画——stop()方法的使用  焦点电影公司作品,电影焦点结局是什么?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  详解CentOS6.5 安装 MySQL5.1.71的方法  如何登录建站主机?访问步骤全解析  佛山企业网站制作公司有哪些,沟通100网上服务官网?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  phpredis提高消息队列的实时性方法(推荐)  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  canvas 画布在主流浏览器中的尺寸限制详细介绍  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  如何在Windows虚拟主机上快速搭建网站?  如何快速查询网址的建站时间与历史轨迹?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  简单实现Android验证码  PythonWeb开发入门教程_Flask快速构建Web应用  详解阿里云nginx服务器多站点的配置  高端建站如何打造兼具美学与转化的品牌官网?  原生JS获取元素集合的子元素宽度实例  南京网站制作费用,南京远驱官方网站?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  如何批量查询域名的建站时间记录?  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  想要更高端的建设网站,这些原则一定要坚持!  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  Laravel如何实现用户密码重置功能?(完整流程代码)  *服务器网站为何频现安全漏洞?  如何在腾讯云免费申请建站?  Linux系统命令中tree命令详解  如何彻底卸载建站之星软件?  Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】  用v-html解决Vue.js渲染中html标签不被解析的问题  EditPlus中的正则表达式实战(5)  CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】