—进程控制 上篇

Posted the_scent_of_th_soul

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了—进程控制 上篇相关的知识,希望对你有一定的参考价值。

linux系统的一个重要特点就是:可以同时启动多个进程。那么什么是进程呢?
(一)进程概念:进程简单地讲就是运行中的程序。它是一个动态的实体,是程序的一次执行过程。另外,进程是操作系统资源分配的基本单位。
进程与程序不同,程序是一些保存在硬盘上的可执行的代码,是静态的。
(二)进程操作:
每个进程都由ID号标识,进程被创建时系统会为其分配一个唯一的进程ID。
1.创建进程:除了极少数以特殊方法创建的进程(如init进程)外,系统调用fork是创建一个新进程的唯一方法。进程调用fork函数就创建了一个子进程。
fork函数的声明及其功能如下:

pid_t fork(void);     /*调用一次返回两次*/
int main(void)

    pid_t pid;
    char * msg;
    int k;
    pid=fork();    /*Create a child process*/
    switch(pid)
        case 0:msg="child process is running";
               k=3;
               break;
        case -1:printf("process creation is fail\\n");
                break;
        default :msg="parent process is running";
                 k=5;
                 break;
    
    while(k>0)
        puts(msg);
        sleep(1);
        k--;
    
    exit(0);

从输出上可以看到,switch语句被执行了两次,一次是在子进程中执行,一次是在父进程中执行。fork返回值有两个,一个是父进程调用fork函数后的返回值:刚建的子进程的ID,另一个是子进程中fork函数的返回值:0。
一般来说,fork之后是子进程还是父进程先执行是不确定的,这取决于内核所使用的调度算法。除非某进程的优先级比其他进程高,否则操作系统让所有进程享有同等执行权。由while语句输出的内容可以发现,父子进程其实是交替执行的
注:可以用ps命令查看进程的当前状态。
vfork函数也可以用来创建一个新进程,它其实是调用了fork函数。与fork的异同点主要如下:
(1)vfork与fork一样,都是调用一次,返回两次。
(2)fork创建的子进程完全复制父进程的资源,子进程独立于父进程,具有良好的并发性。vfork创建的子进程共享父进程的地址空间,完全运行在父进程的地址空间上,子进程对该地址空间中任何数据的修改同样为父进程所见。
(3)fork创建的子进程运行的先后取决于调度算法,vfork保证子进程先运行。

个人觉得创建守护进程涉及的内容比较多,所以有关守护进程的内容我将在下篇说明,这里暂时先不提及。

2.进程退出

在 main 函数中中执行return 
调用exit或者_exit函数          /*正常退出*/
调用about函数
进程接受某个使程序终止的信号     /*异常退出*/

不管哪一种退出方式,最终都会执行内核中的同一段代码。这段代码用来关闭进程所有已打开的文件描述符,释放它所占用的内存和其他资源。
另外,父子进程终止的先后顺序不同会产生不同的结果,具体将在下篇和守护进程一块儿说明。

3.执行新程序
几个进程同时执行一个应用程序通常用处不大,常见的使用方法是子进程在被fork后通过调用exec函数执行另外一个程序。
系统调用exec用于执行一个可执行程序以代替当前进程的执行映像。exec调用并没有生成新进程。一个进程一旦调用exec函数,它本身就 ”死亡了“,系统把代码段替换成新的程序的代码段,废弃原有的数据段和堆段,并为新程序重新分配,唯一保留的就是进程ID。也就是说,对于系统而言,还是同一个进程,不过执行的已经是另外一个程序了。
exec函数族里有很多不同定义的函数,但是无论是哪一个exec函数,事实上都是将可执行程序的路径、命令行参数、和环境变量3个参数传递给可执行程序的main函数。
引入一下环境变量的概念:包括用户的主目录、终端类型、当前目录等,它们定义了用户的工作环境,所以称为环境变量。下面是简单的环境变量应用的代码:

//extern char ** environ;
int main(int argc, char *argv[], char ** environ)

    int i;
    printf("Argument\\n");

    for(i=0; i<argc; i++)
        printf("argv[%d] is %s\\n", i, argv[i]);
    
    printf("Environment\\n");

    for(i=0; environ[i] != NULL; i++)
        printf("%s\\n", environ[i]);
    

可以把第一行的注释去掉,把main函数的第三个参数去掉。会发现,得到的结果是一样的。

以上是关于—进程控制 上篇的主要内容,如果未能解决你的问题,请参考以下文章

新IT运维时代 | Docker运维之最佳实践-下篇

一口气看完MySQL--下篇

iOS多线程开发之GCD(下篇)

Linux调度系统全景指南(下篇)

php 上个产品,下个产品(上篇新闻,下篇新闻)

详细介绍spring框架(下篇)