南宁网站制作工具,如何管理wordpress网站模板下载,wordpress添加公告,电脑建设银行怎样设置网站查询文章目录 一、进程优先级1.1 什么是优先级#xff1f;1.2 为什么会有优先级#xff1f;1.3 小结 二、Linux系统中的优先级2.1 查看进程优先级2.2 PRI and NI2.3 修改进程优先级2.4 进程优先级的实现原理2.5 一些名词解释 三、环境变量3.1 基本概念3.2 PATH#xff1a;Linux系… 文章目录 一、进程优先级1.1 什么是优先级1.2 为什么会有优先级1.3 小结 二、Linux系统中的优先级2.1 查看进程优先级2.2 PRI and NI2.3 修改进程优先级2.4 进程优先级的实现原理2.5 一些名词解释 三、环境变量3.1 基本概念3.2 PATHLinux系统中的指令搜索路径3.3 HOME3.4 USER 四、命令行参数4.1 命令行参数的作用4.2 main函数的第三个参数4.3 环境变量可继承的验证 五、本地变量与内建命令5.1 在bash命令行输入的指令并不一定都要创建子进程 六、结语 一、进程优先级
1.1 什么是优先级
优先级决定了资源分配的先后顺序即谁先访问谁后访问。要注意区分优先级和权限的概念权限决定了能不能做而优先级是在已经确定可以做的基础上去决定谁先谁后的问题。
1.2 为什么会有优先级
因为在系统中可能存在多个进程但是只有一个 CPU这就注定了所有的进程是需要去竞争 CPU 资源操作系统必须保证所有的进程良性竞争即让每个进程都能使用到 CPU 资源。这就像去食堂买饭如果大家不排队都去抢饭那么弱小的人永远也抢不到饭。而排队的顺序就需要通过优先级来确定优先级高的排在前面优先级低的排在后面。如果因为优先级设计不合理调度算法设计不合理导致我们的进程长时间得不到 CPU 资源该进程的代码长时间无法得到推进就会产生该进程的饥饿问题在用户看来就是应用卡死。
1.3 小结 CPU 资源分配的先后顺序就是指进程的优先权。 优先级高的进程有优先执行权利。配置进程优先级对多任务环境的 Linux 很有用可能会改善系统性能注意不要随意的修改进程优先级只有调度器能够最公平的帮我们调度进程。 还可以把进程运行到指定 CPU 上这样一来把不重要的进程安排到某个 CPU可以大大改善系统整体性能。
二、Linux系统中的优先级
2.1 查看进程优先级
//process.c
int main()
{ while(1) { printf(I am a process, PID:%d, PPID:%d\n,getpid(),getppid()); sleep(1); } return 0;
}//通过ps -al 指令可以查看进程的优先级ps -al | head -1 ; ps -al | grep processUID代表执行者的身份。 PID代表这个进程的代号。 PPID代表这个进程是由哪个进程发展衍生而来的即父进程的代号。 PRI代表这个进程可被执行的优先级其值越小越早被执行是 task_struct 结构体对象中的一个成员。 NI代表这个进程的 nice 值是进程优先级的修正数据。
2.2 PRI and NI PRI 即进程的优先级或者通俗点说就是程序被 CPU 执行的先后顺序此值越小进程的优先级别越高。 NI 就是我们呢常说的 nice 值表示进程可被执行的优先级的修正数值。 PRI 值越小越快被执行那么加入 nice 值后将会使得 PRI(new) PRI(old) nice。 当 nice 值为负数的时候那么该程序的优先级值将会变小即优先级会变高其会越快被 CPU 执行。 所以调整进程优先级在 Linux 下就是调整进程的 nice 值。 nice 值的取值范围是[-20,19]一共40个级别。
2.3 修改进程优先级
普通用户是无法修改进程优先级的因此要修改进程优先级必须切换成 root 用户。
top
//进入top后按“r”-输入进程PID-输入nice值小TipsPRI(new) PRI(old) nice中的 PRI(old) 永远都是从80开始。
2.4 进程优先级的实现原理 修改进程的优先级本质上就是修改进程 PCB 对象所在的队列将进程的 PCB 对象链入到修改后优先级对应的数组下标处不同的下标就对应不同的优先级队列。
2.5 一些名词解释 竞争性系统进程数目众多而 CPU 资源只有少量甚至1个所以进程之间是具有竞争属性的。为了高效完成任务更合理竞争相关资源便具有了优先级。 独立性多进程运行需要独享各种资源多进程运行期间互不干扰。 并行多个进程在多个 CPU 下分别同时运行这称之为并行。 并发多个进程在一个 CPU 下采用进程切换的方式在一段时间之内让多个进程都得以推进称之为并发。
并发情况下操作系统会根据每个进程的时间片去进行进程切换当前正在被 CPU 调度的进程在它的时间片结束还没有执行结束会被操作系统从 CPU 上拿下来到上图中的 waiting 数组里面去继续排队等待 CPU 的下一次调度我们把这种过程叫做进程基于时间片轮转的调度算法。那 CPU 在下次调度该进程的时候是如何直到从那里继续执行呢答案是通过程序计数器也叫PC指针是 CPU 中的一个寄存器一般是 epi用于存储下一条将要执行的指令的内存地址这样以来 CPU 下一次再调度该进程的时候就知道该从哪里继续执行了。
小TipsCPU 中的寄存器有很多种例如通用寄存器eax、ebx、ecx、edx和栈帧有关的ebp、esp、eip和状态有关的status。寄存器也有对数据保存的能力计算机在运行时一些重要的数据一定要保存在 CPU 内部即寄存器中因为寄存器离 CPU 很近存储效率高所以 CPU 内的寄存器保存的是进程相关的数据可以随时被 CPU 访问或者修改这种和进程有关的数据也被叫做进程的上下文。进程在从 CPU 上离开的时候。要将自己的上下文数据保存好甚至带走保存好的目的是为了未来恢复。进程在被切换的时候要执行两步操作即保存上下文和恢复上下文进程的上文数据量并不大一般可以直接保存到进程的 PCB 对象中当 CPU 再次调度该进程的时候将这些上下文数据再恢复到寄存器里面即可。
三、环境变量
3.1 基本概念 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数。 如我们在编写 C/C 代码的时候在链接的时候从来不知道我们所链接的动静态库在哪里但是照样可以链接成功生成可执行程序原因就是有相关环境变量帮助编译器进行查找。 环境变量通常具有某些特殊用途还有在系统当中通常具有全局特性。 上图是 Windows 系统下的环境变量本质上就是一组 key-value 接下来将以Linux中的一些现象来演示常见的环境变量。
3.2 PATHLinux系统中的指令搜索路径
我们平时在 bash 命令行中执行自己写的可执行程序时需要加 ./表示当前目录下的可执行程序告诉操作系统执行的时候在该目录下查找指令本质上也是可执行程序但是我们在执行指令的时候却从来没有加任何路径那操作系统是如何直到指令在哪个目录呢之前我们提到过所有的指令都在/usr/bin/目录下而我们自己写的可执行程序是在我们自己当前的工作目录下。都是目录怎么还会有区别呢因为 Linux 操作系统会为我们提供一个环境变量 PATH它是 Linux 操作系统给我们提供的指令搜索路径这个环境变量是自从我们开机登录上 Xshell 就存在的可以通过下面这条指令来查看 PATH 变量的值。
echo $PATHPATH 变量值是用冒号分隔开的一些路径这些路径就是我们平时执行指令时系统去查找指令的路径这就是为什么执行指令的时候不需要加 ./ 因为系统会自动到 PATH 对应的路径下去挨个搜索这些指令都在/usr/bin/目录下并且/usr/bin/目录也是 PATH 的变量值所以指令最终一定会被找到而我们自己写的可执行程序一般都是在当前的工作目录下这个目录并不是 PATH 变量的值如果不加 ./ 操作系统会自动到 PATH 对应的所有路径下挨个去搜索最终都没有找到该可执行程序也就无法执行。可以通过下面这条指令将当前的工作目录添加到环境变量里。
PATH$PATH:/home/wcy/linux-s/lesson13
///home/wcy/linux-s/lesson13是当前工作目录
//只用是覆盖写的意思会把原本的PATH 覆盖掉再去查看 PATH 的值此时我们当前的工作目录也被添加了进去此时在该目录下的可执行程序在执行的时候就可以不加 ./ 了。
小Tips我们上面修改的环境变量是一种内存级的环境变量保存在 shell 中每次登陆 shell 会从系统的一些配置文件中将环境变量加载到 shell 所以我们上面这种修改并不会影响到系统的配置文件因此每次重启登陆环境变量就可以恢复如初。
3.3 HOME
我们每次登陆 shell 都默认处在家目录下这是因为我们每次登陆的时候shell 会识别到当前登陆的用户自动帮我们填充 $HOME 环境变量登陆的时候 shell 会为我们分配命令行解释器 bashbash 本质上也是一个可执行程序它会帮我们执行 cd $HOME 指令这就是为什么我们每次登陆都默认在家目录下。
小Tips我们可以通过 env 指令查看当前 bash 从操作系统中继承下来的所有环境变量。 除了使用 env 指令我们还可以通过 getenv 这个系统调用接口来获取某个环境变量的值。
3.4 USER
通过 USER 这个环境变量可以实现权限的认证不同的用户登录 shell它的 USER 是自己的用户名。
#include stdio.h
#include stdlib.hint main()
{printf(USER:%s\n,getenv(USER));return 0;
}同一份代码不同的用户去执行会得到不同的结果。 #include stdio.h
#include stdlib.h
int main()
{ char user[32]; strcpy(user, getenv(USER)); if(strcmp(root,user) 0) { printf(root用户不受权限约束\n); } else { printf(普通用户受权限约束\n); } printf(USER:%s\n,getenv(USER)); return 0;
} 正式因为 USER 这个环境变量的存在操作系统就具备了识别当前登录用户的能力进而可以和文件对应的拥有者、所属组以及对应的权限做对比一次来判断当前用户是否具有某项权限。
四、命令行参数
C/C 的 main 函数是可以传参的这两个参数就叫做命令行参数如下所示
int main(int argc, char* argv[])
{return 0;
}argv 是一个指针数组里面保存的是字符串地址这个数组有 argc 个元素。
int main(int argc, char* argv[])
{ int i 0; for(; i argc; i) { printf(argv[%d]-%s\n,i, argv[i]); } return 0;
} main 函数做i为函数也是可以被调用的它也有参数调用 main 函数的时候可以传参。我们在 bash 命令行输入的./mycode -a -b -c会被 bash 当成一个字符串它会把这整个字符串以空格作为分隔符分成一个个单独的字符串然后将它们的地址存入到 argv 数组中。
小Tips假设 argc N即有 N 个命令行参数那么 argv[N] 会默认设置成 NULL。
4.1 命令行参数的作用
#include stdio.hint main(int argc, char* argv[])
{ if(argc ! 2) { printf(./mycode [-a|-b|-c|-d]\n); return 0; } if(strcmp(argv[1], -a) 0) { printf(执行功能1\n); } else if(strcmp(argv[1], -b) 0) { printf(执行功能2\n); } else if(strcmp(argv[1], -c) 0) { printf(执行功能3\n); } else if(strcmp(argv[1], -d) 0) { printf(执行功能4\n); } else { printf(没有该选项\n); } return 0;
} 命令行参数有一个重要的作用它可以为指令、工具、软件等提供命令行选项的支持。
4.2 main函数的第三个参数
除了上面提到的 argc 和 argv 两个参数main 函数还有第三个参数 env它也是一个指针数组存放的是该进程的环境变量。
#include stdio.h
int main(int argc, char* argv[], char* env[]) { int i 0; for(;env[i]; i) { printf(env[%d]-%s\n, i, env[i]); } return 0; } 总结我们平时写的 C/C 代码会有两张核心向量表一张叫命令行参数表另一张叫环境变量表。我们平时执行的指令自己写的可执行程序都是 bash 的子进程bash 本身在启动的时候会从操作系统的配置文件中读取环境变量信息子进程会继承父进程交给我的环境变量。这就是环境变量具有全局特性的本质。
4.3 环境变量可继承的验证
通过下面这条指令在 bash 的上下文数据中添加一个我们自己的环境变量通过查看子进程中是否有该环境变量来验证环境变量可以被子进程继承。
export MY_VALUE12345678下面执行子进程 ./mycode可以发现它里面也有 MY_VALUE 这个环境变量说明子进程 mycode 继承了父进程 bash 的环境变量。 正是因为子进程可以继承父进程的环境变量所以我们在 bash 输入的所有指令都要遵守权限因为输入的所有指令都可以看做是 bash 的子进程都继承了 bash 的环境变量。通过下面这条指令可以删除环境变量。
unset MY_VALUE五、本地变量与内建命令
本地变量就是在命令行中直接定义的变量。 可以通过 set 命令查到系统当中的所有环境变量和本地变量。其中本地变量是不会被子进程继承的只会在本 bash 内有效。可以通过 export 指令将一个本地变量变成环境变量。
export MYVALUE
//MYVALUE本来是一个本地变量
//执行完这条指令后MYVALUE就会变成一个环境变量5.1 在bash命令行输入的指令并不一定都要创建子进程
如上图所示我们可以通过 echo 指令打印出本地变量之前说过 echo 作为指令本质上也是一个可执行程序既然是可执行程序那就会创建进程但是我们又说了子进程是无法继承父进程的本地变量那为什么 echo 可以打印出父进程 bash 的本地变量呢原因是并不是所有的指令都会创建子进程。指令可以分为以下两类 常规命令通过创建子进程完成的。 内建命令bash 不创建子进程而是由自己亲自执行类似于 bash 调用了自己写的或者系统提供的函数。
而 echo 就是一个内建命令执行 echo 命令的时候并不会创建子进程与此类似的还有 cd 命令它也是一个内建命令通过调用 chdir 系统接口可以改变当前进程的工作目录。
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h int main(int argc, char* argv[], char* env[])
{ sleep(30); printf(change begin\n); if(argc 2) { chdir(argv[1]); } printf(change end\n); sleep(30); return 0;
} 在 bash 命令行输入 cd 命令的时候bash 并不会创建子进程而是去判断命令行参数是否为 cd如果是就直接去调用 chdir 系统接口切换工作目录。
小Tips除了上面提到的两种通过代码获取环境变量的方法命令行第三个参数、getenv系统接口外还可以通过第三方变量environ获取libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中所以在使用时 要用extern声明。
#include stdio.h
int main(int argc, char *argv[])
{extern char **environ;int i 0;for(; environ[i]; i){printf(%s\n, environ[i]);}return 0;
}六、结语
今天的分享到这里就结束啦如果觉得文章还不错的话可以三连支持一下春人的主页还有很多有趣的文章欢迎小伙伴们前去点评您的支持就是春人前进的动力