0

0

Linux系统进程编程(二)

絕刀狂花

絕刀狂花

发布时间:2025-07-09 11:28:10

|

917人浏览过

|

来源于php中文网

原创

在前一篇文章中,我们已经对进程有了基本的认识,今天我们将继续探讨进程的实际操作——父子进程对文件的操作,以及什么是僵尸进程和孤儿进程?现在让我们揭开这些神秘的面纱!

一、父子进程对文件的操作:

1、子进程继承父进程中打开的文件:

父进程首先使用open函数打开一个文件并获得文件描述符(fd),然后通过fork函数创建子进程。之后,父子进程各自通过write函数向fd中写入内容,代码如下:

#include 
#include 
#include 
#include 
#include 

int main() {
    // 首先打开一个文件
    int fd = -1;
    pid_t pid = -1;
    fd = open("1.txt", O_RDWR | O_TRUNC);
    if (fd < 0) {
        perror("open");
        exit(-1);
    }
    pid = fork();
    if (pid > 0) {
        // 父进程中
        printf("parent.\n");
        write(fd, "IOTNB", 5);
        sleep(1);
    } else if (pid == 0) {
        // 子进程
        printf("child.\n");
        write(fd, "MCU", 3);
        sleep(1);
    } else {
        perror("fork");
        exit(-1);
    }
    close(fd);
    return 0;
}

输出结果:

Linux系统进程编程(二)Linux系统进程编程(二)

说明:我们可以看到,子进程继承了父进程中打开的文件,结果是接续写入(接续写入简单理解为在文件中继续写入内容)。需要注意的是,在实际测试中,有时可能只看到一个写入结果,这看起来像是分别写入,但实际上不是。因为父进程写入后立即关闭了文件,子进程就无法再写入内容。

2、父子进程各自独立打开同一文件实现共享:

现在我们将文件打开操作分别放在父进程和子进程中,看看会有什么效果,代码如下:

#include 
#include 
#include 
#include 
#include 

int main(void) {
    // 首先打开一个文件
    int fd = -1;
    pid_t pid = -1;
    // fork创建子进程
    pid = fork();
    if (pid > 0) {
        // 父进程中
        fd = open("1.txt", O_RDWR | O_TRUNC);
        if (fd < 0) {
            perror("open");
            exit(-1);
        }
        write(fd, "IOTNB", 5);
        sleep(1);
        close(fd);
    } else if (pid == 0) {
        // 子进程
        fd = open("1.txt", O_RDWR | O_TRUNC);
        if (fd < 0) {
            perror("open");
            exit(-1);
        }
        write(fd, "MCU", 3);
        sleep(1);
        close(fd);
    } else {
        perror("fork");
        exit(-1);
    }
    return 0;
}

输出结果:

Linux系统进程编程(二)

说明:最终结果是分别写入。原因是父子进程在分离后各自打开了1.txt,这时这两个进程的PCB已经独立,文件表也独立,因此两次读写是完全独立的。当然,在打开文件操作时,可以通过改变open函数中的参数,使用O_APPEND来实现接续写入。这里不再举例,只需将上面的参数O_TRUNC改为O_APPEND即可。这两个参数的含义在之前的文章中已经详细介绍过。

3、小结:父进程在fork之前所做的事情对子进程有很大影响,但在fork之后,父进程在自己的if语句块中所做的事情对子进程没有影响。本质原因是fork函数内部实际上已经复制了父进程的PCB,并生成了一个新的子进程,并且在fork返回时,子进程已经完全与父进程脱离并独立由操作系统调度执行。

二、僵尸进程和孤儿进程解析:

商城购物系统
商城购物系统

商城购物系统是一个以php+MySQL进行开发的可塑性极强的电子商品平台;商城购物系统可自定义商品栏目内容,包含分销功能,分销管理、分销订单提成完整功能,商品加购物车、商品支付、商品发货等一系列流程,包括pc端和手机H5端。

下载

1、什么是僵尸进程?

提到僵尸可能会让人感到有点害怕,但我们还是回到正题。在Linux系统中,我们需要理解:进程在运行时需要消耗系统资源(内存、I/O),当进程终止时,应该完全释放这些资源(如果进程终止后仍然没有释放相应资源,这些资源就会丢失)。因此,Linux系统设计时规定:每个进程退出时,操作系统会自动回收该进程涉及的所有资源(例如malloc申请的内存没有free时,当前进程结束时这些内存会被释放,open打开的文件没有close时在程序终止时也会被关闭)。然而,操作系统只回收了进程工作时消耗的内存和I/O,而没有回收进程本身占用的内存(8KB,主要是task_struct和栈内存),因为进程本身的8KB内存需要由其他进程来辅助回收。因此,每个进程都需要一个帮助其“收尸”的人,这个角色就是其父进程。所以,僵尸进程是指——子进程先于父进程结束。子进程结束后,父进程不一定立即能够帮其“收尸”,在这一段时间内(子进程已经结束且父进程尚未帮其收尸),子进程就被称为僵尸进程。下面我们来看一个演示:

#include
#include
#include

#define ERR_EXIT(m) \
    do \
    { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main() {
    pid_t  pid;
    if((pid = fork()) == -1)
        ERR_EXIT("fork");
    else if (pid == 0) {
        printf("I am the kid,my pid : %d,my father's pid : %d!\n",getpid(),getppid());
    } else {
        while(1) {
            printf("I am the father,my pid : %d!\n",getpid());
            sleep(2);
        }
    }
    return 0;
}

输出结果:

Linux系统进程编程(二)

2、什么是孤儿进程?

子进程死亡需要父进程来处理,这意味着正常的进程应该是子进程先于父进程死亡。当父进程先于子进程死亡时,子进程死亡时没有父进程处理,这个死亡的子进程就是孤儿进程。同时,Linux系统规定:所有孤儿进程都自动成为一个特殊进程(进程1,也就是init进程)的子进程。下面我来演示一下:

#include 
#include 
#include 

int main(void) {
    pid_t p1 = -1;
    p1 = fork();        // 返回2次
    if (p1 == 0) {
        // 这里一定是子进程
        // 先sleep一下让父进程先运行,先死
        sleep(1);
        printf("子进程, pid = %d.\n", getpid());
        printf("hello world.\n");
        printf("子进程, 父进程ID = %d.\n", getppid());
    }
    if (p1 > 0) {
        // 这里一定是父进程
        printf("父进程, pid = %d.\n", getpid());
        printf("父进程, p1 = %d.\n", p1);
    }
    if (p1 < 0) {
        perror("fork");
        exit(-1);
    }
    return 0;
}

输出结果:

Linux系统进程编程(二)

说明:这里父进程先运行并死亡,但我们后面并没有发现特殊进程init的进程ID为1,而是908,这其实与Ubuntu系统有关,实际应为1。

三、总结:

后续还会继续更新有关进程的文章,今天的学习加深了对进程的进一步理解,后面会介绍回收进程的具体实现方法。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

746

2023.08.22

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

390

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1349

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

702

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

294

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

776

2023.07.05

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

572

2023.07.06

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.3万人学习

swoole入门物联网开发与实战
swoole入门物联网开发与实战

共15课时 | 1.2万人学习

swoole项目实战(第二季)
swoole项目实战(第二季)

共15课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号