【Linux系统编程】进程的认识

简介: 【Linux系统编程】进程的认识

介绍:


       进程是程序执行的实体,可将其理解为程序。比如:当我们使用文本编辑器Notepad应用程序来编写一篇文章时,此时,Notepad应用程序就被加载到了内存中,并且它占用的资源(如内存、CPU等)也得到了分配。在这个过程中,Notepad应用程序就是一个进程,此进程在使用过程将不断被执行,当关闭Notepad应用程序,此进程占用的资源将释放,进程结束。而操作系统则是负责调度和管理这个进程的实体,它为进程分配资源,并在进程结束后回收资源。也就是说,操作系统负责管理进程。


进程控制块

       进程控制块的简称为PCB,是操作系统中用于管理进程的数据结构。它包含了进程的所有状态信息,可以理解为进程属性的集合,用来描述一个进程的所有属性,是进程存在的唯一标志。


       Linux下的PCB(进程控制块)是 task_struct 结构体,此结构体是Linux内核的一种数据结构。而task_struct 结构体中的数据如下:


task_ struct内容分类
标示符: 描述本进程的唯一标示符,用来区别其他进程。
状态: 任务状态,退出代码,退出信号等。
优先级: 相对于其他进程的优先级。
程序计数器: 程序中即将被执行的下一条指令的地址。
内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
其他信息


       使用ps axj指令可查看进程详细信息。其中,PID对应的就是进程的标识符,PPID对应的是父进程的标识符。标识符是用来描述本进程的唯一标示符,用来区别其他进程。

5020a08f64714351a176be00f168d5e6.png



标识符函数

       在写程序时,要想观察此进程的PID可在代码中使用 getpid() 函数,此函数可获得进程的PID,返回类型为pid_t(就是int),即谁调用getpid,就获取谁的PID。对应的还有 getppid() 函数,获取该进程的父进程标识符,返回类型为pid_t(就是int)。


       这里要说明一下,每一次启动程序时,对应的PID都会发生变化,PPID一般不会发生变化,除非您通过某种方式改变了父进程。


       在Linux中,当您启动一个程序时,该程序的PPID通常是被启动该程序的shell进程的PID,即该进程的PPID对应的就是bash或其他shell进程。可以说每启动的一个进程都是bash或shell的子进程。因此说每一次启动进程时,PID都会变化,PPID一般不会变化,除非我们将父进程也改变。


[zhu@zhujunhao day21]$ ll
total 16
-rw-rw-r-- 1 zhu zhu  305 Dec 21 17:07 code.cpp
-rwxrwxr-x 1 zhu zhu 9176 Dec 21 17:07 code.exe
[zhu@zhujunhao day21]$ cat code.cpp    //程序的源代码
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
int main()
{
    pid_t pid = getpid();
    pid_t ppid = getppid();
    sleep(3);
    cout << "该进程对应的PID: " << pid << endl;
    sleep(3);
    cout << "该进程对应的PPID: " << ppid << endl;
    return 0;
}
[zhu@zhujunhao day21]$ ./code.exe
该进程对应的PID: 2248
该进程对应的PPID: 1381
/*下面我们删除程序的进程,再次编译运行后可发现,该进程的PID发生了变化,PPID没有改变。该程序的PPID就是bash或shell进程*/
[zhu@zhujunhao day21]$ rm -f code.exe  
[zhu@zhujunhao day21]$ ll
total 4
-rw-rw-r-- 1 zhu zhu 305 Dec 21 17:07 code.cpp
[zhu@zhujunhao day21]$ g++ -o code.exe code.cpp  
[zhu@zhujunhao day21]$ ./code.exe   
该进程对应的PID: 2257
该进程对应的PPID: 1381

/proc目录

       下面,我们了解一下 /proc目录。/proc目录提供了一种访问系统内核内部数据结构、改变内核设置的机制。用户和应用程序可以通过访问/proc目录中的文件和子目录,来获取系统的信息,并可以改变内核的某些参数。


       其中,/proc/[pid]目录提供了访问和操作进程信息的接口,此接口提供指定进程的各种详细信息,可方便地了解和控制进程的状态和行为。


       这里要说明一下,当使用指令 ll /proc/[pid] 进行详细查看时,对应的cwd是当前进程启动的工作目录,即进程启动时所在的工作目录。exe对应的是可执行程序的工作目录,即进程运行的程序。当修改当前进程或可执行文件的工作目录时,对应的cwd或exe会发生变化。


[zhu@zhujunhao day21]$ ll /proc/1381
........
lrwxrwxrwx 1 zhu zhu 0 Dec 21 16:54 cwd -> /home/zhu/day21   //进程启动的工作目录
........
lrwxrwxrwx 1 zhu zhu 0 Dec 21 16:54 exe -> /usr/bin/bash   //可执行程序的工作目录


创建进程fork初识

       fork函数(没有参数):创建子进程,在fork之后,代码会形成分支形成两个,即代码共享,其中一个是该函数创建的一个子进程。其中,该函数返回值为pid_t,给创建的子进程返回0,父进程返回子进程的PID。


[zhujunhao@bogon code]$ cat test.cpp     //源代码
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
int main()
{
    cout << "PID: " << getpid() << endl;
    int ret = fork();
    cout << "ret = fork(): " << ret << endl;
    sleep(1);
    return 0;
}
[zhujunhao@bogon code]$ ./test.exe     //执行源代码的可执行程序
PID: 9655
ret = fork(): 9656  
ret = fork(): 0

       此函数通常跟 if 条件连用,分别使父子进程执行不同的功能。


[zhujunhao@bogon code]$ cat test.cpp      //源代码
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
int main()
{
    cout << "PID: " << getpid() << endl;
    int ret = fork();
    if (ret == 0)
    {
        cout << "I am Child: PID " << getpid() << "  PPID: " << getppid() << endl;
    }
    else 
    {
        cout << "I am father: PID " << getpid() << "  PPID: " << getppid() << endl;
    }
    sleep(1);
    return 0;
}
[zhujunhao@bogon code]$ ./test.exe   //可执行程序
PID: 10418
I am father: PID 10418  PPID: 3038
I am Child: PID 10419  PPID: 10418


       在执行进程的过程中,若不想执行该进程,通常使用 kill -9 [pid]命令强制终止指定进程的执行。关闭该进程后,不会影响该进程的子进程或父进程,即进程(任意进程,包括父子进程)之间是有独立性的,互相是不能影响,可放心使用。


相关文章
|
3月前
|
Ubuntu Linux Anolis
Linux系统禁用swap
本文介绍了在新版本Linux系统(如Ubuntu 20.04+、CentOS Stream、openEuler等)中禁用swap的两种方法。传统通过注释/etc/fstab中swap行的方式已失效,现需使用systemd管理swap.target服务或在/etc/fstab中添加noauto参数实现禁用。方法1通过屏蔽swap.target适用于新版系统,方法2通过修改fstab挂载选项更通用,兼容所有系统。
281 3
Linux系统禁用swap
|
3月前
|
Linux
Linux系统修改网卡名为eth0、eth1
在Linux系统中,可通过修改GRUB配置和创建Udev规则或使用systemd链接文件,将网卡名改为`eth0`、`eth1`等传统命名方式,适用于多种发行版并支持多网卡配置。
426 3
|
4月前
|
Ubuntu Linux
计算机基础知识:linux系统怎么安装?
在虚拟机软件中创建一个新的虚拟机,并选择相应操作系统类型和硬盘空间大小等参数。将下载的 ISO 镜像文件加载到虚拟机中。启动虚拟机,进入安装界面,并按照步骤进行安装。安装完成后,可以在虚拟机中使用 Linux 系统。
|
4月前
|
存储 Ubuntu Linux
「正点原子Linux连载」第二章Ubuntu系统入门
在图2.8.2.4中,我们使用命令umount卸载了U盘,卸载以后当我们再去访问文件夹/mnt/tmp的时候发现里面没有任何文件了,说明我们卸载成功了。
|
2月前
|
监控 关系型数据库 MySQL
在CentOS系统中,如何统计哪个进程打开了文件描述符?
利用上述方法,你可以有效地监控和统计CentOS系统中的进程打开的文件描述符数量,以帮助排查错误或优化系统配置。通过组合使用各种工具和命令,可以获得对系统状态和行为的深入了解,进而做出相应的调整和
149 5
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
380 0
Linux系统初始化脚本
|
4月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
280 18
|
3月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
331 1
|
3月前
|
监控 安全 Linux
Linux系统提权之计划任务(Cron Jobs)提权
在Linux系统中,计划任务(Cron Jobs)常用于定时执行脚本或命令。若配置不当,攻击者可利用其提权至root权限。常见漏洞包括可写的Cron脚本、目录、通配符注入及PATH变量劫持。攻击者通过修改脚本、创建恶意任务或注入命令实现提权。系统管理员应遵循最小权限原则、使用绝对路径、避免通配符、设置安全PATH并定期审计,以防范此类攻击。
1055 1
|
4月前
|
缓存 监控 Linux
Linux系统清理缓存(buff/cache)的有效方法。
总结而言,在大多数情形下你不必担心Linux中buffer与cache占用过多内存在影响到其他程序运行;因为当程序请求更多内存在没有足够可用资源时,Linux会自行调整其占有量。只有当你明确知道当前环境与需求并希望立即回收这部分资源给即将运行重负载任务之前才考虑上述方法去主动干预。
1644 10