进程相关函数

1.fork()函数与vfork()函数

fork()函数

作用:

用于创建一个新的子进程。它会复制调用它的进程的整个地址空间(内存、文件描述符等)。

返回值

>0,表示执行的父进程,返回值是子进程的PID(进程ID)。

=0,表示执行的子进程。

<0,表示创建子进程失败。

地址空间

父进程和子进程的地址空间是相互独立的。也就是说,父子进程各自有自己的变量副本,对一个进程变量的修改不会影响另一个进程。

相关代码

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();
    
    if (pid < 0) {
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("I am the child process with PID %d\n", getpid());
    } else {
        // 父进程
        printf("I am the parent process with PID %d, child PID is %d\n", getpid(), pid);
    }
    
    return 0;
}

vfork()函数

作用

创建一个新的子进程,但它不会复制父进程的地址空间。子进程与父进程共享一个地址空间,知道子进程调用_exit()或者exec()结束时才分离。

返回值

>0,表示执行的父进程,返回值是子进程的PID(进程ID)。

=0,表示执行的子进程。

<0,表示创建子进程失败。

地址空间

子进程与父进程共享地址空间,因此在子进程中修改变量会影响父进程中的变量。在子进程调用_exit()或者exec()之前,父进程会被阻塞,无法继续执行。

相关代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t pid = vfork();
    
    if (pid < 0) {
        perror("vfork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("I am the child process with PID %d\n", getpid());
        _exit(0); // 子进程立即退出或调用 exec() 系列函数
    } else {
        // 父进程在子进程调用 _exit() 或 exec() 之前被阻塞
        printf("I am the parent process with PID %d, child PID is %d\n", getpid(), pid);
    }
    
    return 0;
}

2.getpid()函数与getppid()函数

getpid()函数

作用

返回当前进程的进程ID(PID)。

用途

用于唯一标识一个进程。每个正在运行的进程都有一个唯一的进程 ID,可以用来区分不同的进程。

getppid()函数


作用

返回当前进程的父进程的进程ID。

用途

用于了解当前进程的父进程是谁。父进程是启动或创建当前进程的进程。

相关代码


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{

        pid_t pid = fork();
        if (pid < 0)
        {
                perror("fork error!\n");
                return -1;
        }
        else if(pid > 0)
        {
                //父进程
                printf("father process\n");
                printf("子进程的Pid = %d\n",pid);
                printf("父进程的pid = %d\n",getpid());
                sleep(5);
        }
        else
        {
                //子进程
                printf("child process\n");
                printf("子进程的pid =%d\n",getpid());
                printf("父进程的pid =%d\n",getppid());
                sleep(10);
        }
        return 0;
}

3.exit()函数与_exit()函数

exit()函数

作用

用于终止当前进程的执行,并向操作系统返回一个状态码。它不仅会终止进程,还会执行一些必要的清理操作,例如关闭文件描述符、刷新 I/O 缓冲区等。

参数

0表示正常退出。

非零值表示异常退出。具体值可以自定义,也可以使用标准定义的宏,例如 EXIT_SUCCESS(一般为 0)和 EXIT_FAILURE(一般为 1)。

_exit()函数

作用

立即终止进程,不进行任何清理操作(不刷新缓冲区、不调用 atexit() 函数),直接返回状态码给操作系统。

总结

exit() 是一种安全终止程序的方法,它会完成所有必要的清理工作。对于普通的进程终止,exit() 是首选;而对于需要立即退出、避免影响父进程的情况(如子进程中的错误处理),则使用 _exit()

4.waitpid

作用

用于使父进程等待特定的子进程结束,并获取其退出状态。它是进程间通信和管理的重要工具,通常用于防止子进程变成僵尸进程。

函数原型

#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);

参数

pid:指定要等待的子进程的进程ID。

status:指向整型变量的指针,用于存放子进程的退出状态。如果不需要获取状态,可以传递NULL。

options:该参数可用于设置等待行为的选项。

重要宏

  • WIFEXITED(status): 检查子进程是否正常退出。

  • WEXITSTATUS(status): 获取子进程的退出状态码(仅当 WIFEXITED 为真时有效)。

  • WIFSIGNALED(status): 检查子进程是否因信号而终止。

  • WTERMSIG(status): 获取导致子进程终止的信号(如果是因信号而终止)。

5.system()函数

函数原型

 #include <stdlib.h>

 int system(const char *command);

参数

command:这是一个指向 C 风格字符串的指针,该字符串包含要执行的命令。该命令会被传递给系统的命令行(Shell)。

注意事项

跨平台差异

system()函数所执行的命令取决于操作系统,例如CLS是Windows的清屏命令,而clear是Linux和MacOS的清屏命令。

安全问题

如果command的内容是用户输入的,则可能会带来安全风险(命令注入)。尽可能避免直接使用用户输入的内容作为system()的参数。

5.exec()族函数

exec()族函数的主要作用是在一个进程内启动另外一个程序。这些函数用于取代当前进程的映射,换句话说就是将当前运行的程序替换为新的程序。

作用

1.进程管理

替换进程映象。exec()函数允许当前进程用新程序的映象替换自己,这意味着可以在同一进程上下文中执行不同的程序,而不需要创建新的进程。

2.执行命令

命令执行。在Shell(是一种命令行界面程序,允许用户与操作系统进行交互)和其他应用程序中,exec()函数用于执行用户输入的命令。通过结婚fork()函数,Shell可以创建子进程并在其中执行命令,然后再返回父进程。

3.灵活的参数传递

多种参数形式。exec()函数族提供多种形式(execl()、execv()等),允许开发者以不同方式传递参数和环境变量,使其适应各种需求。

4.安全性和资源管理

进程隔离。使用exec()进行进程替换可以确保新程序在干净的环境中运行,从而降低了安全风险,并有效管理系统资源。

避免资源泄露。调用exec()后,远进程的资源(如文件描述符等)会被清理,确保资源得到合理管理。

5.适应多任务环境

支持多任务处理。在现代多任务操作系统中,exec()使的程序能够灵活切换和执行不同的任务,提高了系统的灵活性和响应能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值