• Linux-进程描述(4)之进程优先级与进程创建执行


    进程优先级

    进程cpu资源分配就是指进程的优先权(priority)。优先权高的进程有优先执行权利。

    权限与优先级

      权限(privilege)是指在多用户计算机系统的管理中,某个特定的用户具有特定的系统资源使用权力,像是文件夹,特定系统指令的使用或存储量的限制。权限是有或没有的问题,而优先级则是在已经具有了权限而讨论权限大小的问题。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。用“ps -l”指令查看系统进程:

      注意到其中几个很重要的信息,PID(进程的代号)和PPID(父进程的代号)在前面的进程标识符里已经说过。UID代表执行者的身份。什么意思呐?比如说为什么持有身份证才可以在银行办理业务,因为身份证证明了你是中国合法公民,拥有合法权限,你以中国合法公民的身份在柜台办理业务;再比如学生可以在学校里上课、使用教学设施等等,那是他经过一定的手续成为本校的学生,他是以本校学生的身份在学校学习,而老师则以本校教师的身份在学校教书。当我们创建用户时,由我们为新建用户命名和设置密码,同时系统会为我们所创建的用户名关联一个号,就是所谓的用户uid,即用户的身份。通常用户的身份有普通用户和超级用户。进程uid与运行该进程的用户uid相同。PRI即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高,越早被执行。NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。如前面所说,PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。

      由此看出,PR是根据NICE排序的,规则是NICE越小PR越前(小,优先权更大),即其优先级会变高,则其越快被执行。如果NICE相同则进程uid是root的优先权更大。这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行。到目前为止,更需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。如果原来的PRI50,并不是我们给予一个nice=5,就会让PRI变成55.因为是系统“动态”决定的,所以,虽然nice值是可以影响PRI,但最终的PRI仍要经过系统分析后才能决定。

    修改进程优先级

    修改进程优先级的命令主要有两个: nice,renice

    1、一开始执行程序就指定nice值: nice

    # nice -n -5 /usr/local/mysql/bin/mysqld_safe &
    linux nice 命令详解
    功能说明:设置优先权。
    语  法: nice [-n <优先等级>][--help][--version][执行指令]
    补充说明: nice指令可以改变程序执行的优先权等级。
    参  数: -n<优先等级>或-<优先等级>或–adjustment=<优先等级>  设置欲执行的指令的优先权等级。等级的范围从-20-19,其中-20最高, 19最低,只有系统管理者可以设置负数的等级。

    范例一: root给一个nice值为-5,用于执行vi,并观察该进程。

    # nice -n -5 vi &

    注意:

    (1)一般用户的nice值为0~19

    (2)root可用的nice值为-20~19

    (3)一般用户仅可将nice值越调越高,如果本来nice5,则只能调整到大于5nice

    (4)一般用户仅能调整属于自己的进程nice值。

    也就是说,要调整某个进程的优先级,就是“调整该进程的nice值”。

    2、调整已存在进程的nice: renice

     renice -5 -p 5200
     #PID为5200的进程nice设为-5
    linux renice 命令详解
    功能说明:调整优先权。
    语  法: renice [优先等级] [-g <程序群组名称>...] [-p <程序识别码>...] [-u <用户名称>...]
    补充说明: renice指令可重新调整程序执行的优先权等级。预设是以程序识别码指定程序调整其优先权,您亦可以指定程序群组或用户名称调整优先权等级,并修改所有隶属于该程序群组或用户的程序的优先权。等级范围从-20–19,只有系统管理者可以改变其他用户程序的优先权,也仅有系统管理者可以设置负数等级。
    参  数:
    -g <程序群组名称>  使用程序群组名称,修改所有隶属于该程序群组的程序的优先权。
    -p <程序识别码>  改变该程序的优先权等级,此参数为预设值。
    -u <用户名称>  指定用户名称,修改所有隶属于该用户的程序的优先权。

    范例二 : 4222那个PID修改nice为-5

    也可以用top命令更改已存在进程的nice:
     top
     #进入top后按“r”–>输入进程PID–>输入nice值

    进程创建执行

    当进程执行时,它会被装载进虚拟内存,为程序变量分配空间,并把相关信息添到task_struct中。
    进程内存布局分为四个不同的段:
    • 文本段,包含程序的源指令。
    • 数据段,包含了静态变量。
    • 堆,动态内存分区区域。
    • 栈,动态增长与收缩的段,保存本地变量。
      这里有两种创建进程的方法, fork()和execve()。它们都是系统调用,但它们的运行方式有点不同。要创建几个一进程可以执行fork()系统调用。 然后子进程会得到父进程中数据段,栈段和堆区域的一份拷贝。子进程独立可以修改这些内存段。但是文本段是父进程和子进程共享的内存段,不能被子进程修改。
    fork函数用于从已存在进程中创建一个新进程,新进程成为子进程,原进程成为父进程。这两个进程分别返回他们各自的返回值,其中父进程的返回值是子进程的进程号,子进程则返回0,因此返回值大于0标识父进程,等于0标识子进程。所以我们可以通过返回值来判定该进程是父进程还是子进程。fork函数创建新进程后的父子进程模型如下:

    下面用一个简单程序来观察父子进程之间的运行过程:

    该代码运行结果如下:

    fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
        1)在父进程中,fork返回新创建子进程的进程ID;
        2)在子进程中,fork返回0;
        3)如果出现错误,fork返回一个负值;

    fork出错可能有两种原因:
        1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。
        2)系统内存不足,这时errno的值被设置为ENOMEM。
        创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。

    execve()函数创建一个新进程。这个系统调用会销毁所有的内存段去重新创建一个新的内存段。然后,execve()需要一个可执行文件或者脚本作为参数,这和fork()有所不同。注意,execve()和fork()创建的进程都是运行进程的子进程。

      父进程fork一个子进程之后,在已存在的子进程中调用exec函数启动新的程序。新程序替换了当前进程的文本段、数据段、堆、栈。进程ID不改变。exec函数一共有七个,其中execve为内核级系统调用,其他(execl,execle,execlp,execv,execvp,fexecve)都是调用execve的库函数,我们可以使用7个函数中的任意一个。

    函数定义: int execve(const char *filename, char *const argv[ ], char *const envp[ ]);

    返回值: 函数执行成功时没有返回值,执行失败时的返回值为-1;

    函数说明: execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。

    1 #include<unistd.h>   
    2 main()   
    3 {   
    4   char *argv[ ]={"ls", "-al", "/etc/passwd", NULL};   
    5   char *envp[ ]={"PATH=/bin", NULL}   
    6   execve("/bin/ls", argv, envp);   
    7 }  

    运行结果为:-rw-r--r-- 1 root root 1659 Feb 27 20:13 /etc/passwd

    这与在bin目录下执行 ls -al /etc/passwd 所得到的结果是一样的。

    fork是分身,execve是变身。

     exec系列的系统调用是把当前程序替换成要执行的程序,而fork用来产生一个和当前进程一样的进程(虽然通常执行不同的代码流)。通常运行另一个程序,而同时保留原程序运行的方法是,fork+exec。

  • 相关阅读:
    SpringMVC项目模块浅析
    利用python脚本(xpath)抓取数据
    利用python脚本(re)抓取美空mm图片
    Intellij idea开发Hadoop MapReduce程序
    在Hadoop平台跑python脚本
    Hadoop常用命令
    CentOS6.5 安装Zookeeper集群
    MySQL常用命令
    MongoDB常用命令
    前后端分离架构+k8s+ingress
  • 原文地址:https://www.cnblogs.com/33debug/p/6734603.html
Copyright © 2020-2023  润新知