linux-进程概念(3)

文章目录

  • 前言
  • 进程的优先级
    • 改变进程的优先级
  • 其他概念
  • 环境变量
    • 编程中使用环境变量
    • 环境变量的继承

前言

IO就是input和output,IO是站在进程的角度说的。进程向磁盘索要数据叫做I,进程向输出设备刷新数据叫做O。

task_struct{
      //进程的PCB
	//标识符 PID.PPID
	//进程状态
	//...
}

进程的优先级

优先级和权限的区别?
权限是你能不能做这件事。优先级是大家都能做这件事,只是谁先谁后。
优先级什么时候才具有价值?
被管理对象多的时候才有价值。就好比你去食堂吃饭,如果只有你一个人,那么就不需要排队。如果人数很多,那么就需要优先级,谁排在前面谁先吃。所以进程多的时候,同样需要优先级来管理进程。
优先级体现在task_struct中就是一个整数,在task_struct中,数字越小的进程代表优先级越高。优先级的大小可以造成2种operation,仲裁,即多个进程同时想占用资源,那么优先级高的先占用。抢占,一个进程正在使用资源,另一个优先级高的进程过来抢占资源。

ps -l #查看当前用户启动的进程

linux-进程概念(3)_第1张图片
其中的UID是user的id号,就是当前用户的id号。而其中的PRI就是我们进程的优先级,PRI值越小,代表该进程越先被执行。但是还有一列NI,这叫做nice值,是进程优先级的修正数据。我们的优先级实际上等于默认的优先级+NI值。这是什么意思呢?所有进程被创建出来时,默认的优先级都是80,而NI默认是0。如果想要改变进程的优先级,linux采用的是改变NI的方法,一旦NI被改变,优先级也变化。nice值的取值范围是[-20,19],所以优先级的取值范围是[60,99]。要注意的是,进程的优先级可以相同。

改变进程的优先级

一个方法是先使用top命令,注意,进程的优先级除非特殊情况,不然不要改变。因为进程的执行顺序是操作系统管理的,如果冒失的改变,可能会对操作系统造成不利。所以这件事需要sudo。然后按r键,输入进程的PID,然后输入nice值即可。
上面的proc进程优先级是80。我现在将它的优先级改成最低,60.
linux-进程概念(3)_第2张图片
可以看到,NI值变成-20的时候,优先级变成60.但是,接下来我将NI值变成19,那么优先级会是多少呢?60+19 = 79吗?
22
可以看到,NI变成19之后,进程的优先级变成了99!!这说明了优先级的变化是在默认的优先级上变化的,即NI+80才是真正的优先级。

其他概念

  • 竞争性:进程数量众多,但是cpu数量很少,甚至只有1个。所以进程之间有竞争性。而为了合理安排资源,就有了优先级。
  • 独立性:进程具有独立性,在某个时间片内进程是独占资源的,而且一个进程的生死与其他进程无关。
  • 并发:一个进程在运行的时候是直到运行结束才从cpu上下来吗?不是的。操作系统会给每个进程分配时间片,当你的时间片结束或者来了一个优先级比你高的进程的时候,就要换下一个进程。然后所有的进程进行时间片轮转,由于cpu运行速度实在太快,我们看到的假象是多个进程同时运行,这种叫做并发。
  • 并行:多个进程在多个cpu中运行,就可能在同一时间,多个进程同时运行,这叫做并行。
  • 时间片的分配是操作系统说了算,时间片是浮动的,它需要保证对每个进程雨露均沾,而且优先级只能保证你先运行,但是不能保证你运行的时间片长。关于时间片运行,也分为可抢占调度,即来了一个优先级高的进程可以抢占正在运行的进程的时间片,但是这并不是意味着被抢占的进程时间片消失,只是延后了。也有不可抢占调度,在一个进程时间片运行期间,不可被抢占资源。现在大多操作系统都是可抢占调度。

环境变量

你可能听说过环境变量这个名词,但是究竟是什么意思呢?别急,先用一个栗子引入。我们知道在终端中输入命令,就会之间运行。命令本质上是一个可执行程序,但是如果我们想运行自己写的可执行程序,需要这样:

linux-进程概念(3)_第3张图片
这是为什么呢?实际上,执行一个程序,需要两部分,第一,找到它在哪里,即需要它的路径。第二,执行它。ls命令并没有带上路径,这意味着操作系统知道它在哪里。实际上我们有一个PATH的环境变量,里面存的就是操作系统的默认搜索路径,所有的命令都在这些路径里面。你可以使用echo $PATH来查看。
环境变量
这些路径使用冒号分隔。也就是说,当你输入ls的时候,它会去PATH的路径去找,如果找到就执行,找不到就报错。那么问题来了,我们写的可执行程序可以不带路径吗?当然可以,有两种办法,第一,将我们的可执行程序拷贝到PATH路径里面。但是这种方法会污染命令池。第二,我们在路径里面加上一条路径,这种方法的好处是,PATH这个环境变量是在内存中,修改它,那么当系统重启时,PATH会重置回默认状态。也就是说,修改路径是暂时的。我们修改路径的办法是使用export:
linux-进程概念(3)_第4张图片
你也可以使用unset删除终端中的环境变量。
我们还有一系列的环境变量,我们可以使用env命令查看:
其中我们需要了解的还有,SHELL环境变量表示当前终端的shell类型。HOME记录了当前用户的默认工作目录,当你进入linux,为什么会进入默认的工作目录?答案就是linux使用HOME环境变量记录了。
现在我们再来看看环境变量是什么。既然是变量,那么一定是变量名字=内容。环境变量实质是一些具有全局作用的变量,目的是满足某些系统需求。实际上还是为了使用者或者开发者操作便利,想一想你每次执行命令还有带上路径,那太痛苦了。

编程中使用环境变量

main函数是有参数的。你可能知道,

int main(int argc, char* argv[]){
     }

第一个参数表示命令行参数的个数,第二个参数是一个指针数组,这个指针数组指向的内容就是参数行的内容。第一个是进程本身的名字。

// proc
    #include   
    using namespace std;
  
    int main(int argc, char* argv[]){
     
    for(int i = 0; i < argc; ++i){
     
     cout << "argv[" << i << "]" << ":"<< argv[i] << endl;                                                                    
   }
    return 0;
  }

上面的代码输出的是命令行输入的信息。
linux-进程概念(3)_第5张图片
可以看到执行结果,第0个argv是命令本身,然后接下来是所有的命令行选项。这时候你就可以理解命令带有选项就会呈现不同的结果,因为可以根据命令行参数进行分流,使得不同选项附带不同的结果。默认的情况下argv数组的最后一个元素是NULL,也是说argv[argc] == NULL。
linux-进程概念(3)_第6张图片

但你可能不知道,main还可以有第三个参数,

int main(int argc. char* argv[], char* env[]){
     }

这里的env也是一个指针数组,代表所有的环境变量,而env数组的最后一个元素也是NULL。我们写一个程序来证明这件事。

#include 
using namespace std;

int main(int argc, char *argv[], char *env[]){
     
	for(int i = 0; argv[i]: ++i){
     
		cout << i << " : " << argv[i] << endl;
	}
}

这个程序会打印所有的环境变量。你可能会疑惑,main的参数是谁传递的?是操作系统。它帮助我们传递参数。我们还有别的办法在函数中使用环境变量吗?有的。

linux-进程概念(3)_第7张图片
getenv函数可以帮助我们获得一个环境变量。这个函数的参数是环境变量的名字,返回的是环境变量的内容。下面是模拟pwd的程序,使用环境变量PWD和getenv函数。
linux-进程概念(3)_第8张图片

环境变量的继承

环境变量是具有全局性的,这体现在子进程可以继承父进程的环境变量。你可能会想getenv的环境变量来自哪里呢?继承自它的父进程,也就是bash。但是你的自定义变量不能够被继承。

myval=100        #像这样直接在终端定义的变量是无法被继承的。
export myval=100 #这样可以

实际上文件系统是树状结构,所以1号进程的环境变量export后,所以的进程都会继承,这也是环境变量具有全局性体现。

你可能感兴趣的:(Linux,linux,运维)