首页 > 系统相关 >Linux进程状态

Linux进程状态

时间:2024-09-13 21:20:49浏览次数:3  
标签:状态 文件 pid num Linux 进程 buf ptr

进程的生老病死

进程状态

说进程是动态的活动的实体,指的是进程会有很多种运行状态,一会儿睡眠、一会儿暂停、一会儿又继续执行。下图给出Linux 进程从被创建(生)到被回收(死)的全部状态,以及这些状态发生转换时的条件:

请添加图片描述

进程与程序

1、程序通常时一个静态的可执行文件。
2、进程是程序运行动态体现。
3、在windos下可执行文件类型是exe; 通常在Linux下可执行文件类型是ELF,Linux中可执行文件没有固定后缀。
4、进程是系统管理的最小单位。

ELF格式文件类型

1、可执行文件
2、可重定位文件:.o .a (静态库)
3、共享目标文件:.so (动态链接库)
4、核心转储文件:.dump

// 查看可执行文件a.out的头部信息
readelf -h a.out

struct task_struct结构体位置:
/usr/src/linux-headers-4.15.0-142-generic/include/linux/sched.h

查看进程的命令

pstree // 查看系统进程树
ps -ef // 查看系统中当前进程
top - H // 动态查看系统中当前进程
htop // 动态查看系统中当前进程(需要自行安装插件)
// sudo apt-get install htop

init属于整个系统中最顶层的进行(没有父进程)
其余进程都有父进程

创建子进程——fork()

  • 功能:创建一个新的进程
  • 头文件:#include <unistd.h>
  • 原型:pid_t fork(void);
  • 返回值
    • 成功0或者大于0的正整数
    • 失败-1
  • 注:该函数执行成功之后,将会产生一个新的子进程,在新的子进程中其返回值为 0,在原来的父进程中其返回值为大于0的正整数,该正整数就
    是子进程的 PID

请添加图片描述

要着重注意的几点:
  fork( )会使得进程本身被复制(想想细胞分裂),因此被创建出来的子进程和父进程几乎是一模一样的,说“几乎”意味着子进程并不是 100%为一份父进程的复印件,他们的具体关系如下:
  父子进程的以下属性在创建之初完全一样,子进程相当于搞了一份复制品:

  1. 实际 UID 和 GID,以及有效 UID 和 GID。

  2. 所有环境变量。

  3. 进程组 ID 和会话 ID。

  4. 当前工作路径。除非用 chdir()加以修改

  5. 打开的文件。

  6. 信号响应函数。

  7. 整个内存空间,包括栈、堆、数据段、代码段、标准 I0 的缓冲区等等。

而以下属性,父子进程是不一样的:

  • 进程号 PID。PID 是身份证号码,哪怕亲如父子,也要区分开
  • 记录锁。父进程对某文件加了把锁,子进程不会继承这把锁。
  • 挂起的信号。这些信号是所谓的“悬而未决”的信号,等待着进程的响应,子进程也不会继承这些信号。

​ 子进程会从 fork( )返回值后的下一条逻辑语句开始运行。这样就避免了不断调用fork()而产生无限子孙的悖论。
​ 父子进程是相互平等的:他们的执行次序是随机的,或者说他们是并发运行的,除非使用特殊机制来同步他们,否则你不能判断他们的运行究竟谁先谁后。
​ 父子进程是相互独立的:由于子进程完整地复制了父进程的内存空间,因此从内存间的角度看他们是相互独立、互不影响的。

例:

int main(int argc,char *argv[])
{
    //1、 num 在父子进程中对应的虚拟内存地址相同,
    // 但不是同一空间,因此在父进程中修改num,不会影响子进程中num的值
    //int num = 10;

    // 2、堆空间和数据也会被子进程复制,但实际空间相互独立,操作互不影响
    //int* ptr = (int*)malloc(4);
    //*ptr = 11;
    
    // 3、文件操作
    // 子进程会赋值当前的文件描述符,当父进程读取一段数据之后,子进程再进行读取时,文件指针已经偏移。
    // 原因:num、ptr堆栈数据的存在与否会受当前程序影响,而文件的存在通常不受当前程序影响。
    int fd = open("head.h", O_RDWR);

    pid_t pid = fork();

    if (pid < 0)
    {
        perror("fork fail");
        return -1;
    }

    if (pid == 0) // 子进程
    {
        //1、
        //sleep(1);
        //printf("I'm Son! &num = %p\n", &num);

        //2、
        //sleep(1);
        //printf("son ptr=%p, *ptr=%d\n", ptr, *ptr);

        //3、
        printf("\nson fd = %d\n", fd);
        char buf[100];
        bzero(buf, sizeof(buf));
        read(fd, buf, 80);
        puts(buf);
    }

    if (pid > 0) // 父进程
    {
        //1、
        //num++;
        //printf("I'm Parent! &num = %p\n", &num);

        //2、
        //*ptr = 100;
        //printf("parent ptr=%p, *ptr=%d\n", ptr, *ptr);

        //3、
        printf("\nparent fd = %d\n", fd);
        char buf[100];
        bzero(buf, sizeof(buf));
        read(fd, buf, 80);
        puts(buf);
    }

    pause();

    return 0;
}

进程中加载新的程序文件——execl()

  • 功能:在进程中加载新的程序文件或者脚本,覆盖原有代码,重新运行

  • 头文件:#include <unistd.h>

  • 原型:int execl(const char *path, const char *arg, …);

  • 参数:

    • file:即将被加载执行的 ELF 文件或脚本的名字
    • arg:以列表方式罗列的 ELF 文件或脚本的参数
    • argv:以数组方式组织的 ELF文件或脚本的参数
    • envp:用户自定义的环境变量数组
  • 返回值

    • 成功:不返回
    • 失败:-1

注:

  1. 被加载的文件的参数列表必须以自身名字为开始,以 NULL为结尾。比如要加载执行当前目录下的一个叫做 a.out 的文件,需要一个参数"abcd",那么正确的调用应该是:
    execl(“./a.out”, “a.out",“abcd", NULL),
    或者:
    const char *argv[3]= {“a.out", “abcd”, NULL};
    execv(“./a.out”, argv);
  2. exec函数簇成功执行后,原有的程序代码都将被指定的文件或脚本覆盖,因此这
    些函数一旦成功后面的代码是无法执行的,他们也是无法返回的。

例:

int main()
{
    // 创建一个子进程
    pid_t pid = fork();
    if (pid == 0)
    {
        // 子进程
        //execl("/bin/ls", "ls", "-l", NULL);

        printf("我还在!\n"); // 无法被执行
        sleep(5);
        printf("我走了!\n"); // 无法被执行
    }
    if (pid > 0)
    {
         父进程
        //while(1)
        //{
        //    puts("hello");
        //    sleep(1);
        //}
    }
    return 0;
}

标签:状态,文件,pid,num,Linux,进程,buf,ptr
From: https://blog.csdn.net/qixi_ao/article/details/142220513

相关文章

  • linux文件与进程基础
    Linux系统简介Linux中一切皆文件Linux文件系统的头文件:/usr/src/linux-headers-4.15.0-142-generic/include/linux/fs.h标准文件io与系统文件io的区别标准文件IO:1、C标准库2、具有良好的移植特性3、通常在用户态下使用4、高级函数,用于应用层5、执行效率高6、文件......
  • 《Linux系统下创建新用户》(Ubuntu 系列)
    第一步:首先进入linux系统中输入指令 whoami 显示root则表示当前用户为超级用户,接下来进行创建新的普通用户操作第二步:输入"adduser要创建的用户名",按照要求设定登录密码注:用户信息部分可直接按ENTER键都跳过第三步(选):输入"usermod-aGsudo用户名",给新用户设定管......
  • 【linux】centos7不支持更新后,yum源失效问题!
    1、yum安装时提示该错误。Couldnotretrievemirrorlisthttp://mirrorlist.centos.org/?release=7&arch=aarch64&repo=os&infra=stockerrorwas14:curl#6-"Couldnotresolvehost:mirrorlist.centos.org;未知的错误"原因:yum源官方不支持更新了,要换源2、先备份源mv/e......
  • [linux 驱动]内核定时器详解与实战
    目录1描述2结构体2.1timer_list3相关函数3.1DEFINE_TIMER3.2add_timer3.3del_timer3.4msecs_to_jiffies3.5usecs_to_jiffies5示例4延迟工作队列delayed_work4.1结构体4.1.1delayed_work4.2相关函数4.2.1DECLARE_DELAYED_WORK4.2.2INIT_DELAYE......
  • [linux 驱动]i2c总线设备驱动详解与实战
    目录1描述2结构体2.1bus_type2.2i2c_bus_type2.2.1i2c_device_match2.2.2i2c_device_probe2.2.3i2c_device_remove2.2.4i2c_device_shutdown2.2i2c_adapter2.3i2c_algorithm2.4i2c_driver2.5i2c_client3i2c核心3.1注册i2c适配器3.2注册i2c设备......
  • 搭建图片站时,服务器应该选择 Linux 还是 Windows 系统?
    在选择服务器操作系统时,Linux和Windows都有其各自的优势,对于搭建图片站来说,以下是一些考虑因素:Linux系统:性能和资源消耗:通常,Linux系统比Windows更轻量级,它在资源消耗上更少,对于相同的硬件配置,Linux服务器通常可以提供更好的性能。成本:大多数Linux发行版都是免费的,而且开源的,这意味......
  • windows 使用linux系统。wsl 安装使用
    windows使用wslWSL(WindowsSubsystemforLinux)是适用于Linux的Windows子系统。它是一种在Windows计算机上运行Linux环境的功能,无需传统虚拟机或双启动设置即可让开发人员同时访问Windows和Linux的功能。通过WSL,用户可以直接在Windows上使用Linux应用程序、实......
  • 10、Linux文本编辑器
    文本编辑器常见文本编辑器WindowsNotepad(记事本)SublimeUltraEditLinuxVI/VIMnanoEmacsSedgeditKateVI和VIM的区别VI全称:VisualInterface创建时间:1976年创建者:BillJoyVIM全称:VIIMproved,即VI的升级版创建时间:1991年创建者:BramMoolenaar特点......
  • Linux rm命令详解使用:掌握安全删除技巧
    rm命令用于删除文件和目录。在Linux中,删除操作通过rm命令直接进行,并且不会像Windows系统那样将文件移动到回收站。因此,删除时需要格外谨慎。基本语法rm[选项]文件/目录常用选项-i:删除前进行提示,确认后再删除。-f:强制删除,忽略不存在的文件,不提示。-r或-R:递归......
  • Linux下Shell脚本实现统一管理服务启停重启
    公司今年开始了大批量的裁员,人心惶惶,所以强迫自己学习点新知识,刚好领导给找了个事情,让写个脚本实现一键启停Linux服务器上的服务,于是开始研究这个怎么搞。最开始的时候,有点想当然了,觉得一键启停不就是写个菜单,调用一下服务启动停止的命令就可以实现,但是在写的过程中,发现全是坑,搞......