浅谈Linux的进程

本文深入探讨Linux中的进程管理,包括进程控制块(PCB)的结构,如PID、状态、优先级等,以及进程的组织方式、查看方法、不同状态(如运行、睡眠、僵尸状态)及其影响,还介绍了进程优先级的概念和调整方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程

在学习进程之前,提出一个问题,操作系统是怎么进行进程管理的呢?很简单,就是先去把进程描述起来,再把进程组织起来。

概念:程序的一个执行实例,正在执行的程序,从内核的观点来说,就是担当分配系统资源(CPU时间,内存)的一个实体,

一、描述进程——PCB

进程信息被放在一个叫做进程控制块的结构中,可以理解为进程属性的集合,称之为:PCB,在Linux下,PCB是一个叫做task_struct的结构体,这个结构体里面存放了进程的有关信息。

task_struct结构体的内容分类:

①标识符(PID):描述本进程的唯一的标识符,用来区别其他进程

获取pid的方法有很多,最推荐的一种就是通过系统调用getpid()来获取进程的pid,

②状态:任务状态,退出码,退出信号等

状态分类:R运行状态(runing)  S睡眠状态(sleeping) D磁盘休眠状态(Disk sleeping) T停止状态(stopped) X死亡状态(dead) Z僵尸状态(zombie) 

③优先级:相对于其他进程的优先级

PRI:进程可执行的优先级,值越小优先级越高

NI:代表nice值,表示进程可被执行的优先级的修正数值

④程序计数器:程序中即将被执行的下一条指令的地址

⑤内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针

⑥上下文数据:进程执行时处理器的寄存器中的数据

⑦I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表

⑧记账信息:可能包括处理器的时间总和,使用的时钟数总和,时间限制,记账号等

⑨其他信息

task_struct结构里面还存放了很多的有关进程的信息,我们只罗列出比较常用几点信息,如果有兴趣可以在深入学习

二、组织进程

因为进程需要不断的关闭和开启,和数据结构中链表的结构很相似,所以运行在系统的进程都以task_struct链表的形式存在内核里面,此时我们就把进程组织起来了

三、查看进程

现在进程已经被描述和组织起来,那么有些方法可以让我们查看进程呢?

①进程信息可以被  /proc  文件查看; 比如:要查看PID(进程的标识符)为1的进程,就需要查看  /proc/1  这个文件夹

②通过系统调用获取进程标识符:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(){
      printf("pid:%d\n",getpid());
      printf("ppid:%d\n",getppid());
      return 0;
 }
Tip:getppid()函数是获取父进程的标识符,getpid()函数是获取子进程的标识符
四、创建进程

通过系统调用创建进程,也就是使用fork()函数

此时我们先去运行一段代码:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(){
       pid_t ret = fork();
     printf("hello proc:%d,ret = %d\n",getpid(),ret);
       return 0;
  }
运行结果:


我们在代码中只有一个printf语句,但是为什么 会有两个输出语句呢?

原因就是:fork在创建进程的时候,有两个返回值,给父进程返回子进程的pid,给子进程返回0,此时父子进程代码共享,数据各自开辟空间,私有一份

   所以在父进程中,getpid得到的是:2526(父进程的pid),给父进程返回的ret是子进程的pid,也就是2527,

      在子进程中,getpid得到的是:2527(子进程的pid),给子进程返回的ret是0,所以显示ret = 0;所以就显示了两个printf;

Tip:父子进程执行的先后顺序不确定,是取决于编译器自己。

五、进程的状态

R运行状态(running):表明进程要么在运行中,要么在运行队列里面

S睡眠状态(sleeping):意味着进程在等待事件的完成,这个睡眠也叫做可中断睡眠

D磁盘休眠状态(Disk sleep):这个状态的睡眠通常在等待I/O的结束,也叫做不可中断睡眠

T停止状态(stopped):可以发送SIGSTOP信号给进程,让进程停止。也可以发送SIGCONT信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里面看到这个状态

Z僵尸状态(zombie):子进程退出,父进程没有读取子进程的退出码,子进程进入Z状态

我们现在代码演示一下僵尸进程:

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
      pid_t id = fork();
      if(id<0){
          perror("fork failed!\n");
          return 1;
      }
      else if (id>0){//这个循环里面,我们让父进程sleep30s
          printf("father pid:%d\n",getpid());
          sleep(30);
      }
      else {//这个循环里面,我们让子进程sleep5s,之后退出
          printf("child pid:%d\n",getpid());
          sleep(5);
          exit(EXIT_SUCCESS);
      }
      return 0;
}
运行这段代码之后,在5s之后子进程退出,父进程还在s状态,那么此时子进程的退出码并没有被父进程去接收,此时子进程会进入Z状态。

我们可以在shell中打开另外一个终端,编写脚本来检测进程的状态

这是我们编写的脚本:


运行脚本之后,就可以在终端屏幕上看到程序进入了僵尸状态:


僵尸进程的危害:

①因为进程的状态必须被维护,退出状态也属于进程的基本信息,所以就保存在PCB中,在Z状态中,子进程不退出,PCB就要一直被维护

②子进程进入僵尸状态之后会一直占用内存,造成内存的资源浪费

③内存的泄漏

在这里我们在提一个概念:

孤儿进程,

上面的僵尸状态的例子是子进程先退出,父进程后退出的僵尸进程,而,孤儿进程是父进程先退出,子进程后退出而造成的僵尸进程,用代码实现的话,就是把上面的代码简单的修改一下,此时就不单独举例了。

孤儿进程出现后,这个进程就会被1号init进程领养

六、进程的优先级

概念:CPU资源分配的先后顺序,就是进程的优先级

首先我们在命令行中查看系统进程,输入:ps -l


UID:代表执行者的身份

PID:进程的标识符

PPID:该进程的父进程的标识符

PRI:进程的优先级,数值越低,优先级越高

NI:代表nice值,优先级的修正数值

Tip:PRI值越小,优先级越高,加上nice值之后,PRI(new) = PRI(old) + nice,如果nice值是负数,那么加上nice之后,优先级就变高。

调整进程优先级,在Linux下就是调整nice值

nice的取值范围在:-20 到19

修改进程优先级的命令:  nice  和  renice

①启动进程前的调整

开始执行程序就指定nice值:nice -n -5  ./test

②调整已存在的进程的nice值:

renice  -5 -p 5525  //把PID为5525的进程的优先级该为-5

其他概念的:

①竞争性:优先级是为了更合理的竞争相关资源

②独立性 :多进程运行需要独享各种资源,多进程运行期间互不干扰

③并行:多个进程分别在多个CPU下同时进行,这个称之为并行

④并发:多个进程在一个CPU下,采用进程切换的方式,在一段时间内,让多个进程都能够运行,称之为并发,因为切换时间太短,宏观看来像是一起进行


限于编者水平,文章难免有缺漏之处,欢迎指正!

Tip:如需转载,请注明出处



### Linux 离线环境下 Ollama 的安装与使用 #### 安装准备 为了在Linux离线环境中顺利部署Ollama,需提前在外网连接的机器上准备好必要的文件。这些文件包括但限于`ollama-linux-${ARCH}.tgz`以及`install_ollama.sh`等必需组件[^2]。 #### 修改安装脚本适应离线环境 由于目标环境处于断网状态,在原本依赖于在线资源获取的方式再适用的情况下,应当调整原版安装脚本内的curl或其他下载指令,使之能够读取事先已转移至本地存储介质上的对应版本软件包。具体而言就是更改URL地址为实际存放位置的绝对路径或者相对路径。 #### 执行定制化后的安装过程 当上述准备工作完成后,则可以在目标Linux服务器上面运行经过编辑过的shell script来进行最终的产品落地工作;此阶段可能涉及到解压tarball档案、设置权限等一系列常规操作步骤。 #### 启动服务验证成果 考虑到并非所有的Linux发行版都会预设启用systemd作为初始化管理器,对于那些采用其他机制比如sysvinit的地方来说,就需要按照官方文档指导或是社区经验分享里提到的方法去激活OLLAMA的服务进程了——这一步骤可以通过直接调用可执行程序实现,也可以编写相应的service unit file来达成目的。 #### 数据迁移确保一致性 鉴于同操作系统之间可能存在差异化的用户家目录结构设计,所以从MACOS平台迁移到LINUX时要注意源端`.ollama`文件夹内所含有的各类配置项能否被正确识别解析,并且要特别留意目标路径应设定为`/usr/share/ollama/.ollama/`而非个人用户的home下[^1][^3]。 ```bash cp -r ~/.ollama /usr/share/ollama/ ``` #### 验证模型可用性 最后也是至关重要的一环便是检验整个流程下来是否达到了预期效果,即检查指定端口号处是否有活跃监听活动存在(通常是127.0.0.1:11434),以此证明API接口已经正常对外开放访问权限给客户端应用程序调用了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值