Linux进程控制 Part 1

Linux进程控制

Linux系统任务管理的方法

在Linux中,所有执行的程序都会以进程的形式加载到内存中,进程=PCB+代码和数据,PCB里包含进程运行的各种信息

PCB的原型

Linux的内核PCB其实就是一个非常复杂的结构体,里边我们这节课只关注两个属性,pid(进程id)和ppid(父进程id)

Linux查看获取进程id的方式

pid_t pid=getpid();		//获取pid
pid_t ppid=getppid();	//获取ppid
fork();					//创建子进程

eg:

//示例代码
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
  pid_t id=fork(); 
  if(id==0)
  {
    while(1)
    {
      printf("i am a child process,my pid:%d ppid:%d\n",getpid(),getppid());
      sleep(1);
     }
  }
  else{ 
    while(1)
    {
      printf("i am a parent  process,my pid:%d ppid:%d\n",getpid(),getppid());
      sleep(1);
     }
  }
  return 0;
}

这个C程序运行起来是这样的结果:

在这里插入图片描述

现象解释

当程序执行到fork函数以后,系统会创建一个子进程,子进程和父进程暂时共享fork函数后边的代码和数据,这时候会有一个颠覆大家常识的现象,就是fork函数是有返回值的,我们创建了一个子进程,fork会对子进程返回0值,对父进程返回子进程的pid。这时候一定会想,一个变量怎么会同时赋值两个不同的值呢

那是因为每个进程都有相同范围的地址空间,地址空间和实际物理空间地址还有一层页表的转化,地址空间指向一个页表,页表指向实际物理空间,当创建子进程时候,父子进程的地址空间是一致的,当子进程需要对程序数据进行修改或者操作的时候,子进程的页表会自动指向一块新的空间,来存放或者修改变量值。这也称为写时拷贝。这也可以解释为什么一个变量可以存在多个不同的值了

eg:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

int main()
{
  int a=10;
  pid_t id=fork();
  while(1)
  {
    if(id)
      printf("parent process:a=%d\n",a);//parent process
    if(id==0)
    {
      a=0;
      printf("child process:a=%d\n",a);//child process
    }
    sleep(1);
  }
  return 0;
}

在这里插入图片描述

运行结果:

在这里插入图片描述

Linux 进程的状态

首先学习查看进程状态的命令

ps aux / ps axj

运行结果为:

在这里插入图片描述

常见的几种状态

R 运行状态 并不意味着在运行,也有可能在运行队列中

S 睡眠状态 意味着进程中在等待时间完成

D 磁盘休眠状态 等待IO结束

T 停止状态 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

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

Z 僵尸状态 进程已死亡,并未被任何进程读取,就会一直存在僵尸状态,此时也是存在资源占用的,存在内存泄漏的风险

僵尸进程的危害

进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护?是的!
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!内存泄漏?是的!

孤儿进程:

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
父进程先退出,子进程就称之为“孤儿进程”
孤儿进程被1号init进程领养,当然要有init进程回收喽。

孤儿进程不会存在内存泄漏的问题,在父进程退出后,由一号进程收养,自然也包括回收。

进程优先级

概念:

1、cpu资源分配的先后顺序,就是指进程的优先权(priority)。
2、优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
3、还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

在linux或者unix系统中,用ps –l命令则会类似输出以下几个内容:
在这里插入图片描述

UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :代表这个进程的nice值

PRI and NI

PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
所以,调整进程优先级,在Linux下,就是调整进程nice值
nice其取值范围是-20至19,一共40个级别。

查看进程优先级的命令
//top
//top后按->"r"->输入进程pid->键入修正nice值

环境变量

概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数

如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

常见的环境变量

PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。

查看环境变量的方式:

echo $NMME//NAME:你的环境变量名称

测试PATH

eg:

#include <stdio.h>
int main()
{
    printf("hello world!\n");
    return 0;
}
  1. 对比./hello执行和之间hello执行
  2. 为什么有些指令可以直接执行,不需要带路径,而我们的二进制程序需要带路径才能执行?
  3. 将我们的程序所在路径加入环境变量PATH当中, export PATH=$PATH:hello程序所在路径
  4. 对比测试
  5. 还有什么方法可以不用带路径,直接就可以运行呢?

解释说明

export 是导入环境变量的作用,但是只在内存层面的,每次重启会恢复原样,要永久修改还是需要修改配置文件的

详解环境变量

每个程序都会收到一张环境表(char env[]),环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串*

在这里插入图片描述

通过代码获取

#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{
    int i = 0;
    for(; env[i]; i++)
    {
    	printf("%s\n", env[i]);
    }
    return 0;
}

环境变量特性:

环境变量通常是具有全局属性,可以被子进程继承下去

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栗悟饭&龟波气功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值