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

news2024/11/15 7:23:08

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

    • 前言
    • 预备知识
    • 一、 父进程等待子进程退出(一)
      • 1.1 为啥要等待子进程退出
      • 1.2 父进程等待子进程退出并收集退出状态
      • 1.3 编程验证僵尸进程
        • 1.3.1 程序代码
        • 1.3.2 程序运行结果
      • 1.4 主进程用于等待子进程wait函数介绍
        • 1.4.1 man手册介绍
        • 1.4.2 status参数介绍
      • 1.5 程序验证wait的status参数为空起到防止僵尸进程
        • 1.5.1 程序代码
        • 1.5.2 程序运行结果
      • 1.6 wait函数配合WEXITSTATUS(status)解析子进程终止状态
        • 1.6.1 程序代码
        • 1.6.2 程序运行结果
    • 二、 父进程等待子进程退出(二)
      • 2.1 wait和waitpid函数的区别
        • 2.1.1 wait函数执行次序
        • 2.1.2 waitpid函数介绍
        • 2.1.3 wait和waitpid的区别
      • 2.2 waitpid非阻塞编程实战
        • 2.2.1 程序代码
        • 2.2.2 程序运行结果
      • 2.3 孤儿进程介绍
        • 2.3.1 孤儿进程的定义
        • 2.3.2 孤儿进程编程实战
      • 2.4 Linux典型代码解析
    • 三、 exec族函数
      • 3.1 exec族函数详细介绍
      • 3.2 利用execl函数实现操作当前根目录下的可执行文件
        • 3.2.1 可执行文件程序代码
        • 3.2.2 可执行文件程序运行结果
        • 3.2.3 利用execl函数实现操作当前根目录下的可执行文件代码
        • 3.2.4 利用execl函数实现操作当前根目录下的可执行文件代码运行结果
      • 3.3 利用excel函数使用ls命令
        • 3.3.1 ls命令目录查找
        • 3.3.2 利用excel函数使用ls命令程序代码
        • 3.3.3 利用excel函数使用ls命令程序运行结果
      • 3.4 利用execl函数使用date命令
        • 3.4.1 date命令介绍
        • 3.4.2 利用execl函数使用date命令程序代码
        • 3.4.3 利用execl函数使用date命令程序运行结果
      • 3.5 echo $PATH命令介绍
        • 3.5.1 echo $PATH命令执行结果
        • 3.5.2 采用export PATH = $PATH + 路径修改环境变量
      • 3.6 利用execlp函数使用命令ps
        • 3.6.1 利用execlp函数使用命令ps程序代码
        • 3.6.2 利用execlp函数使用命令ps程序运行结果
      • 3.7 利用execv和execvp使用ps命令
        • 3.7.1 利用execv和execvp使用ps命令程序代码
        • 3.7.2 利用execv和execvp使用ps命令程序运行结果
      • 3.8 使用exec族函数的作用
      • 3.9 exec配合fork使用验证exec族函数的作用
        • 3.9.1 实现的功能
        • 3.9.2 不用exec族函数修改配置文件程序代码
        • 3.9.3 不用exec族函数修改配置文件程序运行结果
        • 3.9.4 使用exec族函数修改配置文件程序代码
        • 3.9.5 使用exec族函数修改配置文件程序运行结果
    • 四、 system函数
      • 4.1 system函数详细介绍
      • 4.2 使用system函数运行可执行文件system_text
        • 4.2.1 system_text可执行文件程序代码
        • 4.2.2 使用system函数运行可执行文件system_text程序代码
        • 4.2.3 使用system函数运行可执行文件system_text程序运行结果
      • 4.3 使用system函数修改配置文件TEST.config的内容
        • 4.3.1 修改配置文件TEST.config程序代码
        • 4.3.2 使用system函数修改配置文件TEST.config的内容程序代码
        • 4.3.3 4.3.2 使用system函数修改配置文件TEST.config的内容程序运行结果
    • 五、 popen函数
      • 5.1 popen函数详细介绍
      • 5.2 system和popen使用命令ps对比
        • 5.2.1 system函数使用命令ps程序代码
        • 5.2.2 system函数使用命令ps程序运行结果
        • 5.2.3 popen函数使用命令ps程序代码
        • 5.2.4 popen函数使用命令ps程序运行结果
    • 结束语

前言

  本篇博文将引领您继续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

结束语

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【47 Pandas+Pyecharts | 杭州二手房数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 过滤数据2.3 行政区处理2.4 地址处理2.5 房屋信息处理2.6 面积处理2.7 楼层处理2.8 年份处理2.9 房价处理2.10 删除不用的列2.11 数据类型转换2.12 查看…

【数学建模】Matlab 编程

MATLAB是美国MathWorks公司自20世纪80年代中期推出的数学软件&#xff0c;具有优秀的数值计算能力和卓越的数据可视化。由于Maltab编程方便&#xff0c;有大量内部函数和工具箱可以使用&#xff0c;作图也 十分方便&#xff0c;因此在数学实验和数学建模竞赛中&#xff0c;我们…

揭秘紧固件分销网络:如何成为结构安全和社会进步的关键支点?

全球产品分销的历史源远流长&#xff0c;早在国际贸易初期就已形成。在紧固件行业中&#xff0c;随着各行业对紧固件需求的不断增长&#xff0c;市场呈现出积极的发展趋势。紧固件在结构、机械、设备及其他众多组件中扮演着至关重要的角色&#xff0c;确保了整个系统的高效运行…

电子家谱族谱在线制作小程序开发

电子家谱族谱在线制作小程序开发 电子家谱在线制作小程序通常会提供一系列的功能来帮助用户创建和维护家谱。这里是一个基于市场上常见的家谱制作小程序的功能列表示例&#xff1a; 基本信息录入&#xff1a; 用户注册与登录个人信息录入&#xff08;姓名、性别、出生日期、照…

隐藏你的环境文件!否则你的云存储数据可能会被盗并被勒索

网络犯罪分子正在侵入组织的云存储容器&#xff0c;窃取其敏感数据&#xff0c;并且在一些情况下&#xff0c;受害组织还会向他们支付费用&#xff0c;以确保他们不泄露或出售被盗数据。 研究人员表示&#xff1a;“此次活动背后的攻击者可能利用了广泛的自动化技术来成功且快…

车载网络测试实操源码_使用CAPL脚本对CAN总线上的错误帧进行实时监控

系列文章目录 车载网络测试实操源码_使用CAPL脚本解析hex、S19、vbf文件 车载网络测试实操源码_使用CAPL脚本对CAN报文的Counter、CRC、周期、错误帧进行实时监控 车载网络测试实操源码_使用CAPL脚本模拟发送符合协议要求(Counter和CRC)的CAN报文 车载网络测试实操源码_使用CA…

企业办公室电脑监控软件有什么好用的推荐(闭眼也可入手)

“工欲善其事&#xff0c;必先利其器。” 在今日之商业战场&#xff0c;企业之兴衰&#xff0c;不仅关乎战略眼光与市场布局&#xff0c;更在于内部管理之精细与效率。 信息技术的飞速发展&#xff0c;企业办公室电脑监控软件应运而生&#xff0c;成为了现代企业管理的得力助…

OpenCV Python 图像处理入门

OpenCV入门 OpenCV&#xff1a;轻量、高效、开源。最广泛使用的计算机视觉工具。 下面涉及图片的读取&#xff0c;RGB彩色通道&#xff0c;区域裁剪&#xff0c;绘制图形和文字&#xff0c;均值滤波&#xff0c;特征提取&#xff0c;模板匹配&#xff0c;梯度算法&#xff0c…

黑马Java零基础视频教程精华部分_19_lambda表达式

系列文章目录 文章目录 系列文章目录一、函数式编程二、Lambda表达式的标准格式三、Lambda表达式的省略写法 一、函数式编程 函数式编程(Functional programming)是一种思想特点。 之前的面向对象:先找对象&#xff0c;让对象做事情。如下图所示&#xff0c;这样会有点小麻烦。…

(一)基于自组织结构的多目标粒子群优化算法(SMOPSO)的无人机三维路径规划(MATLAB代码)

一、无人机多目标优化模型 无人机三维路径规划是无人机在执行任务过程中的非常关键的环节&#xff0c;无人机三维路径规划的主要目的是在满足任务需求和自主飞行约束的基础上&#xff0c;计算出发点和目标点之间的最佳航路。 1.1路径成本 无人机三维路径规划的首要目标是寻找…

理解Pytorch中的collate_fn函数

PyTorch中的DataLoader是最常用的类之一&#xff0c;这个类有很多参数&#xff08;14 个&#xff09;&#xff0c;但大多数情况下&#xff0c;你可能只会使用其中的三个&#xff1a;dataset、shuffle 和 batch_size。其中collate_fn是比较少用的函数&#xff0c;这对初学者来说…

2024年国家数据局第一批20个“数据要素×”典型案例解析

国家数据局首批20个“数据要素”典型案例解析 1、简介1.1 背景简介1.2 典型案例分类 2、案例解析2.1 工业制造领域案例1&#xff1a;数据要素驱动适应多式联运需求的运输装备协同制造案例2&#xff1a;打造工业数据空间 赋能产业链上下游发展 2.2 现代农业领域案例3&#xff1a…

07一阶电路和二阶电路的时域分析

一阶电路和二阶电路的时域分析 时域分析、频域分析、复频域分析本应该在信号与系统&#xff0c;或者数字信号处理这一章节里面进行处理的。 但在电路理论中也有这些知识&#xff0c;那就要好好掌握一下&#xff0c;打个底。详细细致的部分放到信号与系统里面去掌握

Spring Web MVC入门(中)

1. 请求 访问不同的路径, 就是发送不同的请求. 在发送请求时, 可能会带⼀些参数, 所以学习Spring的请求, 主要 是学习如何传递参数到后端以及后端如何接收. 传递参数, 咱们主要是使⽤浏览器和Postman来模拟&#xff1b; 1.1 传递单个参数 接收单个参数&#xff0c;在Spring MV…

七段S型加减速算法原理及其多种形状仿真

1、基本7段S型&#xff1a; 七段S型加减速的位置、速度、加速度、加加速度曲线如下图所示。 加加速度&#xff1a; 加速度&#xff1a; 速度&#xff1a; 位置&#xff1a; 以上是7段S型加减速的最基本公式&#xff0c;在实际应用中还需要考虑到起始和终止速度大于匀速速度的情…

【JavaSE】解读Java中的toString方法

前言&#xff1a; 在Java中&#xff0c;toString方法来自java.lang.Object 类&#xff0c;然后所有对象都继承该Object 类。默认情况下&#xff0c;它的作用是返回对象的字符串表示形式。在实际开发中&#xff0c;重写 toString() 方法可以帮助我们以更易读的形式输出对象信息&…

Verilog基础:模块端口(port)定义的语法(2001标准)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 Verilog中的端口定义有两种风格&#xff0c;一种是Verilog Standard 1995风格&#xff0c;一种是Verilog Standard 2001风格&#xff0c;本文将对Verilog Standar…

C语言基础11指针

指针的引入 为函数修改实参提供支持。 为动态内存管理提供支持。 为动态数据结构提供支持。 为内存访问提供另一种途径。 指针概述 内存地址&#xff1a; 系统为了内存管理的方便&#xff0c;将内存划分为一个个的内存单元&#xff08; 1 个内存单元占 1 个字节&#xff09…

自动控制——状态观测器

自动控制——状态观测器 引言 在自动控制系统中&#xff0c;准确地了解系统的状态对实现高性能控制至关重要。然而&#xff0c;在许多实际应用中&#xff0c;我们无法直接测量系统的所有状态变量。这时&#xff0c;状态观测器&#xff08;State Observer&#xff09;就发挥了…

【LeetCode面试150】——209长度最小的子数组

博客昵称&#xff1a;沈小农学编程 作者简介&#xff1a;一名在读硕士&#xff0c;定期更新相关算法面试题&#xff0c;欢迎关注小弟&#xff01; PS&#xff1a;哈喽&#xff01;各位CSDN的uu们&#xff0c;我是你的小弟沈小农&#xff0c;希望我的文章能帮助到你。欢迎大家在…