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

相关文章

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

linux-基础知识3

打包和压缩 zip 安装zip软件包 yum -y install zip unzip 压缩打包命令: zip -q -r -d -u 压缩包文件名 目录和文件名列表 -q:不显示命令执行过程-r:递归处理,打包各级子目录和文件-u:把文件增加/替换到压缩包中-d:从压缩包中删除指定的文件 解压:unzip 压缩包名 打包文件 把压缩包从服务器下载到本地 把压缩包上传到服务器(zip

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n