栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

【UNIX】进程创建与进程控制相关系统调用函数

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【UNIX】进程创建与进程控制相关系统调用函数

文章目录

Introduction一、创建进程二、控制进程


Introduction

  本文主要讨论在UNIX系统如何通过一系列系统调用函数创建与控制进程,创建进程时用到的系统调用函数主要有:fork()、exec()、wait()等,控制进程用到的系统调用函数主要有:kill()等。下面结合代码详细介绍上述系统调用函数功能。


一、创建进程

  fork()可用于创建一个新的进程,更确切的说,它主要是用于在父进程中创建一个子进程,当调用此函数时,操作系统会为子进程分配其自己的地址空间、寄存器、PC等,子进程运行的代码是父进程代码的复制,但是执行不是从main函数开始,而是从fork()被调用的那行代码开始。fork()的返回值在父进程和子进程中也不一样,父进程中fork()的返回值为子进程的PID,而子进程中fork()的返回值为0.
  当调用fork()函数时,因为CPU调度器的复杂性,父进程和子进程的执行顺序其实是不确定的,此时可以使用wait()函数来控制两个进程的执行,使其执行顺序由不确定变为确定。调用wait()函数可以使执行延迟,直到子进程完成执行。
  除此之外,上面有提到fork()创建的子进程执行的代码是父进程的复制,如果要运行另一个程序可以调用exec()函数,当进程调用exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的main函数开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。使用上述fork()、wait()、exec()函数创建进程的实例代码如下所示:

#include 
#include 
#include 
#include 
#include 

int main(int argc, char *argv[]){
    printf("Hello world! (pid: %d)n",(int) getpid());
    int rc = fork();
    if (rc<0) {
        printf("fork failed!");
    } else if (rc==0){
        printf("I'm child! (pid: %d)n",(int) getpid());
        char *myargs[4];
        myargs[0] = strdup("./add_test");
        myargs[1] = strdup("1");
        myargs[2] = strdup("2");
        myargs[3] = NULL;
        execvp(myargs[0],myargs);
        printf("this shouldn't print out.n");

    } else {
        int rc_wait = wait(NULL);
        printf("I'm father of %d (pid: %d)n",rc,(int) getpid());
    }
}

  上述代码首先调用fork()创建子进程,在父进程分支中调用wait()控制执行顺序,等待子进程执行完后再执行父进程分支内容,子进程中调用了execvp()来执行另一个程序内容,execvp()是exec()函数的其中一个变种,详细解释可见exec函数族。上述子进程执行的程序add_test实现的功能为将终端输入的两个数相加并将结果打印出来,具体代码为:

#include 
#include 
#include 

int main(int argc, char *argv[]){
    int a,b,c;
    a = atoi(argv[1]);
    b = atoi(argv[2]);
    c = a+b;
    printf("the add result is: %d+%d=%dn",a,b,c);
    return 0;
}

  将进程的创建分离为fork()和exec()函数,可以在fork()和exec()之间执行一些代码,这些代码可以改变即将运行的程序环境,从而可以轻松构建各种有趣的功能。shell主要就是调用fork、exec()和wait()实现它的功能;当你在shell里敲下命令的那一刻,shell首先在文件系统中搜索可执行文件的位置,调用fork()函数创建子进程,然后调用exec()函数的变种执行命令,同时调用wait()等待子进程完成运行,当子进程结束运行,shell返回打印prompt等待下一个命令。

二、控制进程

  在大多数UNIX shell中,不同的按键组合被设置成会向当前正在运行的进程传递特定的信号,比如说control-c发送SIGINT信号,control-z发送SIGTSTP信号。这个功能由信号子系统实现,信号子系统提供了丰富的基础设施向进程传递额外的事件,包括用单独的进程来接收和处理这些信号,以及发送信号给特定进程或者整个进程组的方式。对于进程来说,会使用signal()系统调用函数去捕获各种信号,这可以保证当给某个进程传递特定信号时,它会停止执行并运行一些特定的代码以响应这个信号。除此之外,还有专门的系统调用函数可以用来终止程序的运行:kill()。

  虽然fork()函数十分常用,但这也不意味着它没有问题,还有一个也可用于创建进程的函数是spawn(),使用时可以对比一下哪一个更为适用

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/728081.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号