IO就是input和output,IO是站在进程的角度说的。进程向磁盘索要数据叫做I,进程向输出设备刷新数据叫做O。
task_struct{
//进程的PCB
//标识符 PID.PPID
//进程状态
//...
}
优先级和权限的区别?
权限是你能不能做这件事。优先级是大家都能做这件事,只是谁先谁后。
优先级什么时候才具有价值?
被管理对象多的时候才有价值。就好比你去食堂吃饭,如果只有你一个人,那么就不需要排队。如果人数很多,那么就需要优先级,谁排在前面谁先吃。所以进程多的时候,同样需要优先级来管理进程。
优先级体现在task_struct中就是一个整数,在task_struct中,数字越小的进程代表优先级越高。优先级的大小可以造成2种operation,仲裁,即多个进程同时想占用资源,那么优先级高的先占用。抢占,一个进程正在使用资源,另一个优先级高的进程过来抢占资源。
ps -l #查看当前用户启动的进程
其中的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.
可以看到,NI值变成-20的时候,优先级变成60.但是,接下来我将NI值变成19,那么优先级会是多少呢?60+19 = 79吗?
可以看到,NI变成19之后,进程的优先级变成了99!!这说明了优先级的变化是在默认的优先级上变化的,即NI+80才是真正的优先级。
你可能听说过环境变量这个名词,但是究竟是什么意思呢?别急,先用一个栗子引入。我们知道在终端中输入命令,就会之间运行。命令本质上是一个可执行程序,但是如果我们想运行自己写的可执行程序,需要这样:
这是为什么呢?实际上,执行一个程序,需要两部分,第一,找到它在哪里,即需要它的路径。第二,执行它。ls命令并没有带上路径,这意味着操作系统知道它在哪里。实际上我们有一个PATH的环境变量,里面存的就是操作系统的默认搜索路径,所有的命令都在这些路径里面。你可以使用echo $PATH来查看。
这些路径使用冒号分隔。也就是说,当你输入ls的时候,它会去PATH的路径去找,如果找到就执行,找不到就报错。那么问题来了,我们写的可执行程序可以不带路径吗?当然可以,有两种办法,第一,将我们的可执行程序拷贝到PATH路径里面。但是这种方法会污染命令池。第二,我们在路径里面加上一条路径,这种方法的好处是,PATH这个环境变量是在内存中,修改它,那么当系统重启时,PATH会重置回默认状态。也就是说,修改路径是暂时的。我们修改路径的办法是使用export:
你也可以使用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;
}
上面的代码输出的是命令行输入的信息。
可以看到执行结果,第0个argv是命令本身,然后接下来是所有的命令行选项。这时候你就可以理解命令带有选项就会呈现不同的结果,因为可以根据命令行参数进行分流,使得不同选项附带不同的结果。默认的情况下argv数组的最后一个元素是NULL,也是说argv[argc] == NULL。
但你可能不知道,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的参数是谁传递的?是操作系统。它帮助我们传递参数。我们还有别的办法在函数中使用环境变量吗?有的。
getenv函数可以帮助我们获得一个环境变量。这个函数的参数是环境变量的名字,返回的是环境变量的内容。下面是模拟pwd的程序,使用环境变量PWD和getenv函数。
环境变量是具有全局性的,这体现在子进程可以继承父进程的环境变量。你可能会想getenv的环境变量来自哪里呢?继承自它的父进程,也就是bash。但是你的自定义变量不能够被继承。
myval=100 #像这样直接在终端定义的变量是无法被继承的。
export myval=100 #这样可以
实际上文件系统是树状结构,所以1号进程的环境变量export后,所以的进程都会继承,这也是环境变量具有全局性体现。