linux 进程重要知识(详讲)

2023-11-02 03:08

本文主要是介绍linux 进程重要知识(详讲),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、进程基础

1.进程相关概念

  •   进程是一个独立可调度的任务,进程是一个抽象的实体,当系统在执行某个程序时,分    配和释放的各种的资源

  •   进程是一个程序的一次执行的过程

  •   进程是程序执行资源管理的最小单位

  •   进程和程序的区别:进程是动态的概念,它是程序执行的过程,包括创建、调度和消亡

                                   程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有                                       任何执行的概念

                                                 正文段(.test)

                                进程         用户数据段(.data)     程序

                                                系统数据段 

         进程不仅包括程序的指令和数据,而且包括程序计数器值,CPU的所有寄存器以及存储临时数据的进程堆栈

2.linux下的进程结构

    主要的进程标识:进程号(Process Identity Number , PID)

                                父进程号(Parent Process ID,  PPID)

   Linux中的进程包含三个段:

  • 数据段:存放的是全局变量、常量以及动态数据分配的数据空间(如malloc函数取得的空间)等

  • 正文段:存放的是程序中的代码

  • 堆栈段:存放的是函数的返回地址、函数的参数以及程序中的局部变量

3.linux系统的进程类型

  • 交互进程:该进程是由shell控制和运行的。交互进程既可以在前台使用,也可以在后台使用

  • 批处理进程:该进程不属于某个终端,它被提交到一个队列中以便顺序执行

  • 守护进程:该类进程实在后台运行,它一般在linux启动时开始执行,系统关闭时才结束。

4.进程运行状态

  • 运行态(R):此时进程正在运行或者正在准备运行

  • 等待态:此时进程正在等待某一个事件的发生或者某种系统资源(阻塞,休眠,等待,睡眠态)           

              可中断态(S):接收到信号有反应          

              不可中断态(D):接收到信号没有反应

  • 停止态(T):此时进程已经被终止(SIGSTOP信号,SIGCONT信号)

  • 死亡态(Z):这是一个已终止的进程,但还在进程向量数组汇总占有一个task_struct结构体(僵尸态)

进程状态图:

                              

5.进程的模式

  进程的执行模式分为用户模式和内核模式

在系统中,有一个定时器,每隔1ms产生一次中断,中断会进入内核(成为心跳,滴答tick);在用户模式与内核模式切换时,只有发生中断,才能从用户模式进入到内核模式,系统调用都是靠软件进行中断,

6.调度进程

  • ps          查看系统中的进程

  • top        动态显示系统中的进程

  • nice      按用户指定的优先级运行进程

  • renice   改变正在运行的进程的优先级

  • kill         结束进程(包括后台进程)

  • bg          将挂起的进程在后台运行

  • fg           把后台的运行的进程放到前台运行

二、进程系统调用

1.进程创建:fock() 产生一个进程

       头文件:#include<sys/types.h>//提供类型pid_t的定义   #include <unistd.h>

      函数原型:pid_t fock(void);

      函数返回值:0:子进程,从fock返回的地方开始执行

                            子进程PID(大于零的证书):父进程

                            -1:出错

      getpid():获取pid号,子进程号

      getppid():获取ppid号,父进程号

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。(系统启动首先要运行init进程,init扫描孤儿进程,收养孤儿进程)

僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程,通常是由父进程清理子进程的僵尸。

2.exec函数族(替换一个进程的映像)

 fock函数用于创建一个进程,该子进程几乎拷贝了父进程的全部内容

 exec函数族提供了一种在进程中启动另一个程序执行的方法。它可以根据指定的文件名或者目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段、堆栈段。在执行完之后,原调用进程的内容除了进程号外,其他全部都被替换了。

什么时候使用?

 当进程认为自己不能在为系统和用户做出任何贡献了时就可以调用exec函数,让自己执行新的程序。如果某个进程想同时执行另一个程序,它就可以调用fock函数创建子进程,然后在子进程中调用任何一个exec函数。这样看起来就好像通过执行应用程序而产生了一个新进程一样。

      #include <unistd.h>

  •  int execl(const char *path, const char *arg, ... /* (char  *) NULL */);

  •  int execlp(const char *file, const char *arg, .../* (char  *) NULL */);

  •  int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const                                                                     envp[] */);

  •  int execv(const char *path, char *const argv[]);

  •  int execvp(const char *file, char *const argv[]);

  •  int execvpe(const char *file, char *const argv[],char *const envp[]);

exec函数组使用区别:

  • 可执行文件查找方式

  • 参数表传递方式

  • 环境变量的使用

exec函数族使用注意点:

在使用exec函数族时,一定要加上错误判断语句

常见的错误原因有:

  • 找不到文件或者路径,此时errno被设置为ENOENT

  • 数组argy和envp忘记用NULL结束,此时errno被设置为EFAULT

  • 没有对应可执行的的运行权限,此时ERRNO被设置EACESS

3.exit 和 _exit

头文件: exit:#include<stdlib.h> 

               _exit: #include <unistd.h>

函数原型: exit:  void exit(int status);

               _exit:void  _exit(int status);

函数传入值:status是一个证书的参数,可以利用这个参数传递进程结束时的状态,通常()表示正常结束;其他的数值表示出现了错误,进程非正常结束。在实际编程时,可以用wait系统调用接受子进程的返回值,进程相应的处理

_exit和exit的区别:

  • _exit()函数的作用最为简单:直接使进程终止结运行,清除其使用的内存空间,并销毁其在内核中的数据结构

  • exit()函数则在这些基础上做了一些包装,在执行退出之前加了若干道工序

  • exit()函数在调用exit系统调用之前要文件的打开情况,把文件缓冲区中的内容写入文件,就是图中的“清理I/O缓冲”一项

                           

4.wait 和 waitpid

  • wait函数:调用该函数使进程阻塞,直到任一个子进程结束或者是该进程接受到了一个信号为止(等待态,可中断)。如果该进程没有子进程或者其子进程已经结束,wait函数会立即返回。

  • waitpid函数:功能和wait函数类似。不同的是可以指定某一子进程结束以及等待的方式(阻塞或非阻塞)

wait()函数

头文件  #include<sys/types.h>

             #include <sys/wait.h>

函数原型:   pid_t wait(int *status);

函数参数:   status是一个整形指针,指向的对象用来保存子进程退出时的状态。

  •                      status若为空,表示忽略子进程退出时的状态

  •                      status若不为空,表示保存子进程退出时的状态

  •                       另外,子进程的结束状态可由linux中一些特定的宏来测定

waitpid()函数

头文件  #include<sys/types.h>

             #include <sys/wait.h>

函数原型:pid_t waitpid(pid_t pid, int *status, int options)

函数参数:pid

  • pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结                                   束退出了,只要指定的子进程还没 有结束,waitpid就会一直等下去

  • pid =1: 等待任何一个子进程退出,此时和wait作用一样

  •  pid =0:等待其他组ID等于调用进程的组ID的任一子进程

  •  pid<0:  等待七组ID等于pid的绝对值的任一进程

  status:获取子进程结束信息

 options

  • WNOHOG,若由pid指定的子进程并不立即只使用,到waitpid不阻塞,此时返回值为0

  •  WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程已暂停,且其状态自暂停以来还来报告过,则返回其状态

  •   0:同wait,苏泽父进程,等待子进程退出

函数返回值:正常:结束的子进程的进程号

                     使用选项WNOHANG且没有子进程结束时:0

                     调用出错:-1

   5.linux守护进程

  • 守护进程,也就是通常所说的Daemon进程,是linux中的后台服务进程,它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件

  • 守护进程常常在系统启动时开始运行,在系统关闭时终止

  • linux系统有很多守护进程,大多数服务都是用守护进程实现的          

  • 在linux中,每一个系统与用户进行交流的界面称为终端。从该终端开始运行的进程都会依附于这个终端,这个终端称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会被自动关闭。

  • 守护进程能够突破这种限制,他从开始运行,直到整个系统关闭才会退出。如果让某个进程不会因为用户或者终端的变化而受到影响,就必须把这个进程变成一个守护进程。

6.linux守护进程编写步骤

(1) 创建子进程,父进程退出

 第一步需要子进程在形式上做到与控制终端的脱离,由于父进程已经先于子进程退出, 子进程编程孤儿进程

pid=fork();
if(pid>0)
{exit(0);
}

(2)在子进程中创建新会话

进程组是一个或多个进程的集合。进程组由进程组ID来唯一表示,每个进程组都有一个组长进程,进程组ID就是组长进程的进程号;

会话期是一个或多个进程组的集合

setsid();

(3)改变当前目录为根目录

通常的做法是让“/”或“/tmp”作为守护进程的当前工作目录

在进程运行过程中,当前目录所在的文件系统时不能卸载的

chdir函数可以改变进程当前工作目录

chdir("/");

(4)重设文件权限掩码

文件权限掩码是指文件权限中被屏蔽掉的对应位把文件权限掩码设置为0,可以增加该守护进程的灵活性。

umask(0);

(5)关闭文件描述符

新建的子进程会从父进程那里继承所有已经打开的文件,在创建新的会话后,该守护进程已经脱离任何控制终端,应当关闭用不到的文件。(一般情况下只需要关闭系统自带的三个文件描述符就行),如果在这里需要打印调试,“先不脱离,关闭”。

close(0);
close(1);
close(2);

                        

 

 

 

 

 

 

 

 

 

 

 

 

 

 

这篇关于linux 进程重要知识(详讲)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327665

相关文章

Linux内核定时器使用及说明

《Linux内核定时器使用及说明》文章详细介绍了Linux内核定时器的特性、核心数据结构、时间相关转换函数以及操作API,通过示例展示了如何编写和使用定时器,包括按键消抖的应用... 目录1.linux内核定时器特征2.Linux内核定时器核心数据结构3.Linux内核时间相关转换函数4.Linux内核定时

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

Linux下屏幕亮度的调节方式

《Linux下屏幕亮度的调节方式》文章介绍了Linux下屏幕亮度调节的几种方法,包括图形界面、手动调节(使用ACPI内核模块)和外接显示屏调节,以及自动调节软件(CaliseRedshift和Reds... 目录1 概述2 手动调节http://www.chinasem.cn2.1 手动屏幕调节2.2 外接显

Linux(centos7)虚拟机没有IP问题及解决方案

《Linux(centos7)虚拟机没有IP问题及解决方案》文章介绍了在CentOS7中配置虚拟机网络并使用Xshell连接虚拟机的步骤,首先,检查并配置网卡ens33的ONBOOT属性为yes,然后... 目录输入查看ZFhrxIP命令:ip addr查看,没有虚拟机IP修改ens33配置文件重启网络Xh

linux实现对.jar文件的配置文件进行修改

《linux实现对.jar文件的配置文件进行修改》文章讲述了如何使用Linux系统修改.jar文件的配置文件,包括进入文件夹、编辑文件、保存并退出编辑器,以及重新启动项目... 目录linux对.jar文件的配置文件进行修改第一步第二步 第三步第四步总结linux对.jar文件的配置文件进行修改第一步进

linux ssh如何实现增加访问端口

《linuxssh如何实现增加访问端口》Linux中SSH默认使用22端口,为了增强安全性或满足特定需求,可以通过修改SSH配置来增加或更改SSH访问端口,具体步骤包括修改SSH配置文件、增加或修改... 目录1. 修改 SSH 配置文件2. 增加或修改端口3. 保存并退出编辑器4. 更新防火墙规则使用uf

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的