初识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数据恢复工具使用【推荐】
下一篇:PHP查询分页的实现代码
下一篇:PHP查询分页的实现代码


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