“从创建到管理,Linux进程编程是你掌握系统资源的金钥匙!“#Linux系统编程之进程【下】

"从创建到管理,Linux进程编程是你掌握系统资源的金钥匙!"#Linux系统编程之进程【下】

前言

  本篇博文将引领您继续Linux系统编程的深入探索,聚焦于进程管理的进阶篇(下篇)。我们将逐一揭开父进程如何优雅地等待子进程退出的面纱,分为两大章节详细阐述,确保您掌握这一关键技巧。随后,我们深入exec族函数的广阔天地,揭示它们如何替换当前进程的映像,执行新的程序。此外,还将介绍system函数与popen函数的独特魅力,展示它们在系统调用和管道通信中的灵活应用。无论您是Linux系统编程的初学者,还是希望深化理解的资深开发者,本博文都将为您提供不可或缺的知识和独到见解。在此,诚挚邀请您先点个赞,再细细品味这些精彩内容,让我们一同开启Linux系统编程的更多可能!

预备知识

  一、C变量
  二、基本输入输出
  三、流程控制
  四、函数
  五、指针
  六、字符串
  七、Linux系统基本操作命令如mkdir,ls -l等。
  八、计算内存知识:堆,栈等

  如果以上知识不清楚,请自行学习后再来浏览。如果我有没例出的,请在评论区写一下。谢谢啦!

一、 父进程等待子进程退出(一)

1.1 为啥要等待子进程退出

  如下图
请添加图片描述

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

  如下图
请添加图片描述

1.3 编程验证僵尸进程

1.3.1 程序代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t fk;
        //pid_t getpid(void);
        int cnt = 0;
        //pid_t fork(void);
        fk = fork();
        if(fk > 0)
        {
        		父进程中没有等待子进程退出
                while(1)
                {
                        printf("This is the parent process,and its PID is %d\n",getpid());
                        sleep(1);
                        printf("cnt == %d\n",cnt);
                }
        }
        else if(fk == 0)
        {
                while(1)
                {
                        printf("This is a child process,and the  child process is %d\n",getpid());
                        sleep(1);
                        cnt++;
                        if(cnt == 5)
                        {
                                exit(0);
                        }
                }
        }



        return 0;
}

1.3.2 程序运行结果

在这里插入图片描述

1.4 主进程用于等待子进程wait函数介绍

1.4.1 man手册介绍
	   使用wait函数必须包含以下两个头文件
	   #include <sys/types.h>
       #include <sys/wait.h>

       pid_t wait(int *status);

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

       int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
1.4.2 status参数介绍

  status参数:是一个整型数指针
  非空:子进程退出状态放在它所指向的地址中。
  空:不关心退出状态
  status参数为空时,虽然不关心退出状态,但能起到防止僵尸进程。

1.5 程序验证wait的status参数为空起到防止僵尸进程

1.5.1 程序代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t fk;
        //pid_t getpid(void);
        int cnt = 0;
        //pid_t fork(void);
        fk = fork();
        if(fk > 0)
        {
                while(1)
                {
                        wait(NULL);      等待子进程结束
                        printf("This is the parent process,and its PID is %d\n",getpid());
                        sleep(1);
                        printf("cnt == %d\n",cnt);
                }
        }
        else if(fk == 0)
        {
                while(1)
                {
                        printf("This is a child process,and the  child process is %d\n",getpid());
                        sleep(1);
                        cnt++;
                        if(cnt == 5)
                        {
                                exit(0);
                        }
                }
        }

        return 0;
}
1.5.2 程序运行结果

  如下图
在这里插入图片描述

1.6 wait函数配合WEXITSTATUS(status)解析子进程终止状态

1.6.1 程序代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t fk;
        //pid_t getpid(void);
        int cnt = 0;
        int status = 10;
        //pid_t fork(void);
        fk = fork();
        if(fk > 0)
        {
                while(1)
                {
                        wait(&status);		等待子进程退出,退出状态返回给status
                        printf("This is the parent process,and its PID is %d\n",getpid());
                        sleep(1);
                        printf("status = %d\n",WEXITSTATUS(status));将status解析输出
                }
        }
        else if(fk == 0)
        {
                while(1)
                {
                        printf("This is a child process,and the  child process is %d\n",getpid());
                        sleep(1);
                        cnt++;
                        if(cnt == 5)
                        {
                         		exit(10);
                        }
                }
        }

        return 0;
}
1.6.2 程序运行结果

  如下图
在这里插入图片描述

二、 父进程等待子进程退出(二)

2.1 wait和waitpid函数的区别

2.1.1 wait函数执行次序

  如果其所有子进程都还在运行,则阻塞。

  如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。

  如果它没有任何子进程,则立即出错返回。

2.1.2 waitpid函数介绍

  函数原型

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

  第一个参数pid的介绍
请添加图片描述

  第三个参数介绍
请添加图片描述
  第二哥参数和wait一样,都是返回子进程退出状态。

2.1.3 wait和waitpid的区别

  wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞

2.2 waitpid非阻塞编程实战

2.2.1 程序代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t fk;
        //pid_t getpid(void);
        int cnt = 0;
        int status = 10;
        //pid_t fork(void);
        fk = fork();
        if(fk > 0)
        {
                while(1)
                {
                        waitpid(fk,&status,WNOHANG);   非阻塞等待子进程结束
                        printf("This is the parent process,and its PID is %d\n",getpid());
                        sleep(1);
                        printf("status = %d\n",WEXITSTATUS(status));
                }
        }
        else if(fk == 0)
        {
                while(1)
                {
                        printf("This is a child process,and the  child process is %d\n",getpid());
                        sleep(1);
                        cnt++;
                        if(cnt == 5)
                        {
                                exit(10);
                        }
                }
        }



        return 0;
}
2.2.2 程序运行结果

  如下图
在这里插入图片描述

2.3 孤儿进程介绍

2.3.1 孤儿进程的定义

  父进程如果不等待子进程退出,在子进程之前就结束了自己的“生命”,此时子进程叫做孤儿进程。
  Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程,pid为1。

2.3.2 孤儿进程编程实战

  程序代码

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

int main()
{
        pid_t fk;
        //pid_t getpid(void);
        int cnt = 0;
        int status = 10;
        //pid_t fork(void);
        fk = fork();
        if(fk > 0)
        {
                printf("This is the parent process,and its PID is %d\n",getpid()); 父进程输出自己的进程标识符后就退出来,造成子进程变成孤儿进程。
        }
        else if(fk == 0)
        {
                while(1)
                {
                        printf("This is a child process,and the  child process is %d\n,Parent pid = %d\n",getpid(),getppid()); 输出子进程和父进程的进程标识符。
                        sleep(1);
                        cnt++;
                        if(cnt == 5)
                        {
                                exit(10);
                        }
                }
        }
        return 0;
}

  程序运行结果:如下图
在这里插入图片描述

2.4 Linux典型代码解析

  如下图:
请添加图片描述

三、 exec族函数

3.1 exec族函数详细介绍

  这里请参见大佬:"云英"的博文。
  点击这里

3.2 利用execl函数实现操作当前根目录下的可执行文件

3.2.1 可执行文件程序代码
#include <stdio.h>

int main(int argc,char *argv[])
{
    int i = 0;
    for(i = 0; i < argc; i++)
    {
        printf("argv[%d]: %s\n",i,argv[i]); 
    }
    return 0;
}
3.2.2 可执行文件程序运行结果
以下代码运行结果基于修改环境变量后
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ ls
echoarg    execl   myls  mypsp   Process_programming2.c  Process_programming4.c  Process_programming6.c
echoarg.c  mydate  myps  mypspp  Process_programming3.c  Process_programming5.c  Process_programming.c
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ echoarg aa bb
argv[0]: echoarg
argv[1]: aa
argv[2]: bb
3.2.3 利用execl函数实现操作当前根目录下的可执行文件代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("./echoarg","echoarg","abc",NULL) == -1)  利用execl函数打开当前目录下的可执行文件echoarg
    {
        printf("execl failed!\n");
        perror("why");            打开失败用perror函数输出错误原因
    }
    printf("after execl\n");
    return 0;
}
3.2.4 利用execl函数实现操作当前根目录下的可执行文件代码运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ gcc Process_programming.c -o execl
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ execl
before execl
argv[0]: echoarg
argv[1]: abc

3.3 利用excel函数使用ls命令

3.3.1 ls命令目录查找

  使用"whereis ls"命令查找

CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1.gz

  以上查找结果为ls在目录:/bin/ls

3.3.2 利用excel函数使用ls命令程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(execl("/bin/ls","ls",NULL,NULL) == -1)
    {
        printf("execl failed!\n");
        perror("why");
    }
    printf("after execl\n");
    return 0;
}
3.3.3 利用excel函数使用ls命令程序运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ gcc Process_programming2.c -o myls
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ myls   
before execl
echoarg    execl   myls  mypsp	 Process_programming2.c  Process_programming4.c  Process_programming6.c
echoarg.c  mydate  myps  mypspp  Process_programming3.c  Process_programming5.c  Process_programming.c

3.4 利用execl函数使用date命令

3.4.1 date命令介绍

  date命令为获取系统当前时间信息。

3.4.2 利用execl函数使用date命令程序代码
代码只需要将利用excel函数使用ls命令程序代码打开路劲出修改一下即可
if(execl("/bin/ls","ls",NULL,NULL) == -1)
修改为:
if(execl("/bin/date","date",NULL,NULL) == -1)
3.4.3 利用execl函数使用date命令程序运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ gcc Process_programming3.c -o mydate
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ mydate
This get system date pro
20240815日 星期四 22:57:10 CST

3.5 echo $PATH命令介绍

  echo $PATH命令的作用是显示当前用户的环境变量PATH的值。PATH环境变量是一个由冒号(:)分隔的目录列表,这些目录是系统在查找可执行文件时所要搜索的目录。当你输入一个命令时,系统会按照PATH环境变量中定义的目录顺序,在这些目录中查找是否存在该命令的可执行文件。

3.5.1 echo $PATH命令执行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ echo $PATH
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin
3.5.2 采用export PATH = $PATH + 路径修改环境变量
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ export PATH=$PATH:/home/CLC/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions    修改环境变量路径为当前文件夹
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ echo $PATH 查看修改后的结果
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin:/home/CLC/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions

3.6 利用execlp函数使用命令ps

3.6.1 利用execlp函数使用命令ps程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("Before execlp\n");
    if(execlp("ps","ps",NULL,NULL) == -1)  多了一个p代表不用加路径就可以找到该命令
    {
        printf("execl failed!\n");
        perror("why");
    }
    printf("after execl\n");
    return 0;
}
3.6.2 利用execlp函数使用命令ps程序运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ gcc Process_programming4.c -o mypsp
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/07_Exec_family_functions$ mypsp
Before execlp
  PID TTY          TIME CMD
34509 pts/0    00:00:05 bash
47308 pts/0    00:00:00 vi
47812 pts/0    00:00:00 ps

3.7 利用execv和execvp使用ps命令

3.7.1 利用execv和execvp使用ps命令程序代码
这两个函数只是将
execlp("ps","ps",NULL,NULL)
换成
char *argv[] = {"ps",NULL,NULL};
execlp("ps",argv);
execv函数需要加路径,execvp不需要加路径。
3.7.2 利用execv和execvp使用ps命令程序运行结果

  程序运行结果和利用execlp函数使用命令ps一样。

3.8 使用exec族函数的作用

  一个进程执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec

3.9 exec配合fork使用验证exec族函数的作用

3.9.1 实现的功能

  当父进程检测到输入为1的时候,创建子进程把配置文件的字段值修改掉。

3.9.2 不用exec族函数修改配置文件程序代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        pid_t pid;
        pid_t fk;
        int data;

        int fdSrc;
        int size;
        char *readBuf = NULL;
        char *p = NULL;
        //pid_t getpid(void);

        printf("father : id = %d\n",getpid());
        //pid_t fork(void);
        while(1)
        {

                puts("Please enter a request");
                scanf("%d",&data);
                if(data == 1)				如果输入1创建子进程
                {
                        fk = fork();               创建进程
                        if(fk > 0)
                        {
							wait(NULL);           主进程等待子进程退出返回退出状态
                        }
                        else if(fk == 0)
                        {


                                fdSrc = open("./TEST.config",O_RDWR); 打开配置文件
                                size =lseek(fdSrc,0,SEEK_END);        计算配置文件大小
                                lseek(fdSrc,0,SEEK_SET);			  光标回归
                                readBuf = (char *)malloc(sizeof(char) * (size+1)); 给读缓冲区分配空间
                                read(fdSrc,readBuf,size +1);		读配置文件
                                printf("readBuf = \n%s\n",readBuf); 输出读到的配置文件

                                p = strstr(readBuf,"LENG  = ");		在读到配置文件中查找修改项
                                if(p == NULL)
                                {
                                        printf("Search failure!");
                                        exit(-1);	查找失败退出
                                }
                                p = p + strlen("LENG  = "); 查找成功让指针p偏移到修改位置
                               *p = '5';					修改参数为字符5
                                lseek(fdSrc,0,SEEK_SET);	光标重新回归
                                write(fdSrc,readBuf,strlen(readBuf));将修改后的数据写入配置文件

                                lseek(fdSrc,0,SEEK_SET);	光标重新回归
                                read(fdSrc,readBuf,size +1); 读取已修改的配置文件
                                printf("readBuf = \n%s\n",readBuf);	输出已修改的配置文件

                                close(fdSrc);				关闭配置文件
                                exit(0);					退出子进程
                        }
                }
                else if(data==0)                            如果输入0,退出父进程
                {
                        return 0;
                }
                else	
                {
                        puts("Wait for input!");
                }


        }

}

3.9.3 不用exec族函数修改配置文件程序运行结果

  如下图
在这里插入图片描述

3.9.4 使用exec族函数修改配置文件程序代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main()
{
        pid_t pid;
        pid_t fk;
        int data;

        int fdSrc;
        int size;
        char *readBuf = NULL;
        char *p = NULL;
        //pid_t getpid(void);

        printf("father : id = %d\n",getpid());
        //pid_t fork(void);
        while(1)
        {

                puts("Please enter a request");
                scanf("%d",&data);
                if(data == 1)			
                {
                        fk = fork();
                        if(fk > 0)
                        {
                                wait(NULL);
                        }
                        else if(fk == 0)
                        {
                                execl("./editcon","editcon","TEST.config",NULL);	使用exec族函数在子进程中调用没有使用exec族函数修改配置文件生成的可执行文件

                        }
                }
                else if(data == 0)
                {
                        return 0;
                }
                else
                {
                        puts("Wait for input!");
                }


        }
}
3.9.5 使用exec族函数修改配置文件程序运行结果

  如下图
在这里插入图片描述

四、 system函数

4.1 system函数详细介绍

  这里参见大佬:"南哥的天下"的博文
  点击这里

4.2 使用system函数运行可执行文件system_text

4.2.1 system_text可执行文件程序代码
#include <stdio.h>

int main()
{
        printf("This is system text!\n");
        return 0;
}
4.2.2 使用system函数运行可执行文件system_text程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(system("./system_text") == -1) 使用system函数运行可执行文件system_text
    {
        printf("execl failed!\n");
        perror("why");
    }
    printf("after execl\n");
    return 0;
}
4.2.3 使用system函数运行可执行文件system_text程序运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/08_System_function$ gcc Process_programming.c -o mysystem
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/08_System_function$ ./mysystem
before execl
This is system text!
after execl

4.3 使用system函数修改配置文件TEST.config的内容

4.3.1 修改配置文件TEST.config程序代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
        int fdSrc;
        int size;
        char *readBuf = NULL;
        char *p = NULL;

        if(argc < 2)
        {
                printf("Program error!\n");
                exit(-1);
        }

        fdSrc = open(argv[1],O_RDWR);
        size =lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readBuf = (char *)malloc(sizeof(char) * (size+1));
        read(fdSrc,readBuf,size +1);
        printf("readBuf = \n%s\n",readBuf);

        p = strstr(readBuf,"LENG  = ");
        
        if(p == NULL)
        {
                printf("Search failure!");
                exit(-1);
        }
        p = p + strlen("LENG  = ");
       *p = '5';
        lseek(fdSrc,0,SEEK_SET);
        write(fdSrc,readBuf,strlen(readBuf));

        lseek(fdSrc,0,SEEK_SET);
        read(fdSrc,readBuf,size +1);
        printf("readBuf = \n%s\n",readBuf);

        close(fdSrc);

        return 0;
}
4.3.2 使用system函数修改配置文件TEST.config的内容程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(system("./myedit TEST.config") == -1) 使用system函数运行myedit可执行文件修改TEST.config文件内容
    {
        printf("execl failed!\n");
        perror("why");
    }
    printf("after execl\n");
    return 0;
}
4.3.3 4.3.2 使用system函数修改配置文件TEST.config的内容程序运行结果
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/08_System_function$ gcc Process_programming2.c -o mysystem2
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/08_System_function$ ./mysystem2
before execl
readBuf = 
SPEED = 3
LENG  = 9
SCORE = 9
LEVEL = 9

readBuf = 
SPEED = 3
LENG  = 5
SCORE = 9
LEVEL = 9

after execl

五、 popen函数

5.1 popen函数详细介绍

  这里参见大佬:"libinbin_1014"的博文
  点击这里
  以下是我的简易原理示意图。

请添加图片描述

5.2 system和popen使用命令ps对比

5.2.1 system函数使用命令ps程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
    printf("before execl\n");
    if(system("ps") == -1)    system函数使用命令ps

    {
        printf("execl failed!\n");
        perror("why");
    }
    printf("after execl\n");
    return 0;
}
5.2.2 system函数使用命令ps程序运行结果

  这是在终端输出

CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/09_Popen_function$ gcc Process_programming.c -o mysystem
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/09_Popen_function$ ./mysystem 
before execl
  PID TTY          TIME CMD
34509 pts/0    00:00:07 bash
47308 pts/0    00:00:00 vi
48087 pts/0    00:00:00 vi
49330 pts/0    00:00:00 mysystem
49331 pts/0    00:00:00 sh
49332 pts/0    00:00:00 ps
after execl
5.2.3 popen函数使用命令ps程序代码
//文件execl.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//函数原型:int execl(const char *path, const char *arg, ...);

int main(void)
{
        char result[1024] = {0};
        FILE *fp = NULL;
        int n_read = 0;


        fp = popen("ps","r"); popen函数使用命令ps返回值给FILE *fp;
        //size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);     
        n_read = fread(result,1,1024,fp);   读取open使用ps命令输出结果

        printf("n_read = %d\n,This read data = \n%s\n",n_read,result);输出读取open使用ps命令的结果

        return 0;
}
5.2.4 popen函数使用命令ps程序运行结果

  这是在输出result字符串

CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/09_Popen_function$ gcc Process_programming2.c -o mypopen
CLC@Embed_Learn:~/Linux_System_Programming/Linux_process_programming/09_Popen_function$ ./mypopen n_read = 197
,This read data = 
  PID TTY          TIME CMD
34509 pts/0    00:00:07 bash
47308 pts/0    00:00:00 vi
48087 pts/0    00:00:00 vi
49451 pts/0    00:00:00 mypopen
49452 pts/0    00:00:00 sh
49453 pts/0    00:00:00 ps

结束语

  非常感谢您的耐心阅读!在您即将离开之际,如果您觉得内容有所收获或启发,不妨动动手指,点个赞再走,这将是对我莫大的鼓励和支持。衷心感谢您的点赞与关注,期待未来能继续为您带来更多有价值的内容!谢谢您!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值