进程

进程的概念

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

int main()
{
        pid_t pid;

        pid = getpid();//getpid 获取线程号

        printf("my pid is %d\n",pid);

        while(1);

        return 0;
}
image.png
image.png
image.png

创建进程函数 fork 的使用

fork() 是 Unix/Linux 系统中创建新进程的核心函数,它像一个”进程分身术”。

一句话理解

fork() 创建当前进程的完全副本(子进程),父子进程从 fork() 返回处开始并行执行后续代码。

函数原型

#include <unistd.h>  // 必须包含的头文件

pid_t fork(void);    // 无参数,返回进程ID

返回值(关键!)

返回值含义
> 0父进程中返回子进程的ID
== 0子进程中返回0
< 0创建失败(错误)

执行流程

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

int main() {
    printf("准备fork (PID=%d)\n", getpid());

    pid_t pid = fork();  //fork();创建一个子进程   //fork返回的值就是子进程的pid//
    //fork之后,父进程和子进程都会从fork()返回的地方继续执行,所以后面的代码会被两个进程分别执行。

    // 注意:从这里开始两个进程并行执行
    if (pid < 0) {  //创建失败(错误)
        // 错误处理
        perror("fork失败");
    } else if (pid == 0) {//子进程中返回0
        // 子进程执行的代码
        printf("我是子进程 PID=%d\n", getpid());
    } else {//父进程中返回子进程的ID
        // 父进程执行的代码
        printf("我是父进程 PID=%d, 子进程PID=%d\n", getpid(), pid);//pid变量是fork返回的子进程的pid
    }

    // 父子进程都会执行到这里
    printf("这条消息来自%s进程\n", (pid == 0) ? "子" : "父");
    return 0;
}
  • 在父进程中,pid变量等于子进程的PID(大于0),所以进入else分支,打印:”我是父进程 PID=父进程ID, 子进程PID=子进程ID”
  • 在子进程中,pid变量等于0,所以进入else if (pid == 0)分支,打印:”我是子进程 PID=子进程ID”

可能的输出:

准备fork (PID=1234)
我是父进程 PID=1234, 子进程PID=1235 //fork返回的值是子进程的pid
这条消息来自父进程
我是子进程 PID=1235
这条消息来自子进程

核心

  • 子进程共享父进程的内存空间
  • 只有当某个进程修改数据时,才会真正复制内存
  • 高效节省内存资源

vfork创建进程

image.png

vfork子进程里面,会修改父进程的值,而fork创建的子进程不会修改父进程代码的值,只有当某个进程修改数据时,才会真正复制内存

fork

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

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = fork();

        if(pid > 0)
        {
                while(1){
                        printf("cnt=%d\n",cnt);
                        printf("this is father print,pid = %d\n",getpid());
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is chilid print, pid = %d\n",getpid());
                        sleep(1);
                        cnt ++;
                        if(cnt == 3)
                        {
                                exit(0);
                        }
                }
        }
        return 0;
}
image.png

vfork –> 保证子进程先运行

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

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = vfork();

        if(pid > 0)
        {
                while(1){
                        printf("cnt=%d\n",cnt);
                        printf("this is father print,pid = %d\n",getpid());
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is chilid print, pid = %d\n",getpid());
                        sleep(1);
                        cnt ++;
                        if(cnt == 3)
                        {
                                exit(0);
                        }
                }
        }
        return 0;
}

image.png
重点:

  • vfork 直接使用父进程存储空间,不拷贝
  • vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行
  • vfork子进程里面,会修改父进程的值,而fork创建的子进程不会修改父进程代码的值,只有当某个进程修改数据时,才会真正复制内存

进程退出

父进程等待子进程退出

image.png

子进程退出状态不被收集,变成僵死进程(僵尸进程)

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

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = vfork();

        if(pid > 0)
        {
                while(1){
                        printf("cnt=%d\n",cnt);
                        printf("this is father print,pid = %d\n",getpid());
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is chilid print, pid = %d\n",getpid());
                        sleep(1);
                        cnt ++;
                        if(cnt == 3)
                        {
                                exit(0);
                        }
                }
        }
        return 0;
}
image.png

父进程等待子进程退出,并收集子进程的退出状态

wait函数

wait() 是 Unix/Linux 中用于进程同步和资源回收的关键函数,它像一个”耐心的父母等待孩子结束”。

函数原型

#include <sys/types.h>
#include <sys/wait.h>  // 必须包含的头文件

pid_t wait(int *status);  // status: 用于存储子进程退出状态

核心功能

  1. 阻塞等待:父进程暂停执行,直到有子进程结束
  2. 回收资源:释放子进程占用的系统资源
  3. 获取状态:了解子进程如何退出(正常/异常) 状态码解析(重点!)
    wait(&status) 中的 status 包含丰富信息,需用宏来解析:
宏函数作用示例
WIFEXITED(status)子进程是否正常退出if (WIFEXITED(status))
WEXITSTATUS(status)获取退出状态码printf("%d", WEXITSTATUS(status))
WIFSIGNALED(status)是否被信号终止if (WIFSIGNALED(status))
WTERMSIG(status)获取终止信号编号printf("%d", WTERMSIG(status))
WIFSTOPPED(status)是否被暂停if (WIFSTOPPED(status))

父进程使用 wait() 阻塞等待任意子进程结束,并获取其退出状态,避免产生”僵尸进程”。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = fork();

        if(pid > 0)
        {
                wait(NULL);
                while(1){
                        printf("cnt=%d\n",cnt);
                        printf("this is father print,pid = %d\n",getpid());
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is chilid print, pid = %d\n",getpid());
                        sleep(1);
                        cnt ++;
                        if(cnt == 3)
                        {
                                exit(0);
                        }
                }
         }

        return 0;
}
image.png

获取子进程退出状态

int main()
{
        pid_t pid;

        int cnt = 0;
        int status = 10;

        pid = fork();

        if(pid > 0)
        {
                wait(&status);//存储子进程退出状态
                printf("child quit, child status = %d\n",WEXITSTATUS(status));
                                                  //WEXITSTATUS获取退出状态码的宏
                while(1){
                        printf("cnt=%d\n",cnt);
                        printf("this is father print,pid = %d\n",getpid());
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is chilid print, pid = %d\n",getpid());
                        sleep(1);
                        cnt ++;
                        if(cnt == 3)
                        {
                                exit(3);//设置退出状态码
                        }
                }
        }

        return 0;
image.png

重点:

  • 使用wait 父进程会阻塞,等待子进程运行完在运行、
  • wait的参数是 整型数指针
  • wait的参数可以为空(NULL)–> 不关心退出状态
 wait(NULL);
  • status: 用于存储子进程退出状态
wait(int *status);  // status: 用于存储子进程退出状态
  • status获取到的状态 要用宏来解析
宏函数作用示例
WIFEXITED(status)子进程是否正常退出if (WIFEXITED(status))
WEXITSTATUS(status)获取退出状态码printf("%d", WEXITSTATUS(status))
WIFSIGNALED(status)是否被信号终止if (WIFSIGNALED(status))
WTERMSIG(status)获取终止信号编号printf("%d", WTERMSIG(status))
WIFSTOPPED(status)是否被暂停if (WIFSTOPPED(status))
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇