您的位置:首页 > 运维架构 > Linux

Linux环境下的进程控制

2016-02-23 18:06 483 查看
1.进程的基本概念

        进程是指正在执行中的程序。当我们在终端执行命令时,Linux就会建立一个进程,而当我们的程序执行完毕时,这个进程就被终止了。Linux是一个多任务操作系统,允许多个用户使用计算机,多个进程并发执行。Linux环境下启动进程主要有两个主要途径:手工启动和调度启动。手工启动又分为前台启动和后台启动。调度启动是指用户可以事先进行调度安排,指定任务运行的时间或者场合,到时候系统就会自动完成一切工作。进程操作包括终止进程、改变进程优先级、查看进程属性等,Linux常见的进程操作的系统命令如下表所示:

命令作用
ps查看系统中的进程
top动态的显示系统中的进程
nice按用户指定的优先级运行
renice改变正在运行进程的优先级
kill终止进程(包括后台进程)
crontab用于安装、删除或者列出用于驱动cron后台进程的任务
bg将挂起的进程放到后台执行
fg把后台进程转到前台执行
2.Linux进程控制
        在Linux环境下创建进程时,系统会分配一个唯一的数值给每个进程,这个数值就称为进程标识符(PID)。

        在Linux中进程标志有进程号(PID)和它的父进程号(PPID)。其中,PID唯一地标识一个进程。PID和PPID都是非零的整数。在Linux中获得当前进程的PID和它的父进程号PPID,需分别调用getpid和getppid函数。

         下面的程序要求显示Linux系统分配给它的进程号和父进程号。

         


          多次运行上述程序,发现每次系统分配进程号都是不一样的,这说明进程号是唯一标识一个进程的。

          Linux环境下与进程相关的主要函数如下表所示:

         

函数名功能
getpid取得当前进程的进程号
getppid取得当前进程的父进程号
exec函数族在进程中启动另一个程序执行
system在进程中开始另一个进程
fork从已存在进程中复制一个新进程
sleep让进程暂停执行一段时间
exit用来终止进程
_exit用来终止进程
wait暂停父进程,等待子进程运行完成
waitpid暂停父进程,等待子进程运行完成
        进程调用fork函数创建一个新进程,由fork创建的新进程被称为子进程。该函数被调用一次,但返回两次,两次返回的区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程PID。子进程和父进程继续执行fork之后的指令。子进程是父进程的复制品。例如,子进程获得父进程数据空间、堆和栈的复制品。注意,这是子进程所拥有的拷贝。父、子进程并不共享这些存储空间部分,通常父、子进程共享代码段。
        下面的程序用fork函数创建一个子进程,在子进程中给变量n赋值3,在父进程中给变量n赋值6,fork调用之后父进程和子进程的变量message和n被赋予不同的值,互不影响。

        


       


        在系统中创建一个进程的目的是需要该进程完成一定的任务,需要该进程执行它的程序代码。在Linux系统中,使程序执行的唯一方法是使用系统调用exec()。在exec()族中有6个函数可以建立子进程,它们是execl、execv、execle、execve、execlp、execvp,函数中的第5、6个字符l、v、e、p表示函数中的参数分别用列表传递方式、字符指针数组传递方式、可指定环境变量及路径自动搜索功能。

        下面的程序用fork函数创建一个子进程,在子进程中,要求显示子进程号与父进程号,然后显示当前目录下的文件信息,在父进程中同样显示子进程号与父进程号。

        


       


       


        进程终止可以分为正常终止和异常终止

        正常终止分为:(a)在main函数内执行return语句,这等效于调用exit。(b)调用exit函数。此函数由ANSI定义,其操作包括调用各终止处理函数,然后关闭所有标准I/O流等(c)调用_exit系统调用函数,此函数由exit调用。  

        异常终止分为:(a)调用abort  (b)由一个信号终止

        设计一个程序,要求子进程和父进程都在显示输出一些文字后分别用exit和_exit函数终止进程。

       


       


       exit()用来正常终止目前进程的执行,并把参数status返回给父进程,而进程所有的缓冲区数据会自动写回并关闭未关闭的文件,而_exit()用来立刻终止目前进程的执行,并把参数status返回给父进程,并关闭未关闭的文件。_exit()不会处理标准I/O缓冲区。

        一个已经终止运行、但其父进程尚未对其进行善后处理的进程称为僵尸进程。使用fork'hanshu创建子进程时,由于子进程有可能比父进程晚终止,父进程终止后,子进程还没终止,子进程就会进入一种无父进程的状态,此时的子进程就成了僵尸进程。为避免这种情况,可以在父进程中调用wait或waitpid函数,使子进程比父进程早终止,而让父进程有机会了解子进程终止时的状态,并自动清除僵尸进程。

      


       


       从上面的函数可以看出子进程成为了僵尸进程,这时可以使用kill命令杀死子进程,当再次运行ps时,两个进程都会消失,这是因为当一个进程退出时,它的子进程被一个特殊进程继承,这就是init进程,它是Linux启动后运行的第一个进程。init进程会自动清理所有它继承的僵尸进程。

        下面的程序,它创建一个子程序,要求子程序显示自己的进程号后暂停一段时间,父进程等待子进程的正常结束,打印显示等待的进程号和等待的进程退出状态。

        


       
cf17



        子进程的结束状态返回后存于status,然后使用下列几个宏可判别子进程结束情况:

            a. WIFEXITED(status),如果子进程正常结束则为非0值。

            b.WEXITSTATUS(status),取得子进程exit()返回的结束代码,一般先用WIFEXITED来判断是否正常结束才能使用此宏。

            c.WIFSIGNALED(status),如果子进程是因为信号而结束则此宏值为真。

            d.WTERMSIG(status),取得子进程因信号而中止的信号代码,即信号的编号,一般会先用WIFSIGNALED来判断后才使用此宏。

            e.WIFSTOPPED(status),如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED时才会有此情况。

            f.WSTOPSIG(status),取得引发子进程暂停的信号代码

        下面的程序在父进程中用waitpid函数等待子进程,子进程结束时通过调用函数exit(3)向父进程发送结束信号,父进程直到接受到子进程结束的信号后才结束等待并且通过宏WIFEXITED(stat_val),取得子进程exit(3)返回的结束代码。

       


       


        下面的程序,要求用户可以选择是否创建子进程,子进程模仿思科(Cisco)1912交换机的开机界面,以命令行的方式让用户选择进入,父进程判断子进程是否正常中孩子。

       


       


       


       


        函数功能:等待子进程中断或结束

        函数原型:pid_t waitpid(pid_t  pid,int * status,int options);

        函数传入值:     pid子进程号     status子进程状态  option可以为0或者后面的or组合

        函数返回值:执行成功则返回子进程号(PID),失败则返回-1,失败原因存于error中

3.守护进程

        守护进程是运行在后台,并且一直在运行的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事情。守候进程是一种很有用的进程,Linux的大多数服务器就是用守护进程实现的。守护进程最重要的特性是后台运行。其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等。这些环境通常是守护进程从执行它的父进程中继承下俩的。最后,守护进程的启动方式有其特殊之处。它可以在Linux】系统启动时从启动脚本/etc/rc.d中启动,也可以由作业控制进程crond启动,还可以由用户终端(通常是shell)执行。

         可以通过ps  -aux命令查看Linux环境下的守护进程。例如:;init系统守护进程、keventd守护进程、kswapd守护进程、portmap端口映射守护进程、cron守护进程、cupsd守护进程等。

         编写守护进程的要点:

                 a、创建子进程,终止父进程

                 b、在子进程中创建新会话

                 c、改变工作目录

                 d、重设文件创建掩码

                 e、关闭文件描述符

         下面编写一个守护进程的实例:设计两段程序,daemon1.c和初始化程序init.c。要求主程序每隔10秒钟向/tmp目录中的日志dae.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。

         


         


         


           函数setsid用来设置新的组进程号

           设计一个程序,要求运行后成为守候进程,守候进程又创建一个子进程,守护进程和它的子进程都调用syslog函数,把结束前的状态写入系统日志文件。

         


        


        


         openlog函数准备做信息记录,syslog函数将信息记录至系统日志文件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息