进程处理操作

一、使用system函数调用进程

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char const *argv[])
{
    //使用标准函数创建自进程
    /*
    const char *__command 使用linux命令直接创建一个子进程
    return:成功返回0 失败返回失败编号
    int system (const char *__command)
    */
    int sysR=system("ping -c 10 www.lxl.com");
    if (sysR != 0 )
    {
        perror("system");
        exit(EXIT_FAILURE);
    }
    
    return 0;
}

makefile

cpp 复制代码
CC:=gcc
system_test:system_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@

二、进程处理相关系统调用

1、main函数说明

2、fork创建子进程

cpp 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int main(int argc, char const *argv[])
{
    //调用fork之前 代码都在父进程中运行
    printf("海哥教老学员%d春暖花开\n",getpid());
    
    //使用fork创建子进程
    /*
    不需要传参
    return int 进程号
    【1】:-1出错
    【2】:父进程中表示子进程的PID
    【3】:子进程中显示为0
    __pid_t fork (void)
    */
    pid_t pid = fork();
    //从fork之后 所有的代码都是在父进程中各自执行一次的
    //printf("%d\n",pid);

    if (pid < 0)
    {
        printf("新学员加入失败\n");
        return 1;
    }
    else if (pid == 0)
    {
        //执行单独子进程代码
        printf("新学员%d加入成功,他是老学员%d推荐的\n",getpid(),getpid());
    }
    else
    {
        //执行单独父进程代码
        printf("老学员%d继续深造,他推荐了%d\n",getpid(),pid);
    }

    return 0;
}

makefile

cpp 复制代码
fork_test:fork_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@

3、使用fork复制文件描述符

cpp 复制代码
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>

int main(int argc, char const *argv[])
{
    //fork之前 父进程单独进

    int fd = open("io.txt",O_CREAT | O_WRONLY |O_APPEND,0644);

    if (fd == -1)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    char buffer[1024];//缓冲区存放写出的数据

    pid_t pid = fork();
    
    if (pid < 0)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else if (pid == 0)
    {
        //子进程代码
        strcpy(buffer,"这是子进程写入的数据!\n");
    }
    else
    {
        //父进程代码
        sleep(1);
        strcpy(buffer,"这是父进程写入的数据!\n");
    }
    
    //父子进程都要执行的代码
    ssize_t bytes_write = write(fd,buffer,strlen(buffer));
    if (bytes_write == -1)
    {
        perror("write");
        close(fd);
        exit(EXIT_FAILURE);
    }
    printf("写入数据成功\n");

    //使用完毕之后关闭
    close(fd);

    if (pid == 0)
    {
        printf("子进程写入完毕,并释放文件描述符\n");
    }
    else
    {
        printf("父进程写入完毕,并释放文件描述符\n");
    }
    

    return 0;
}

makefile

cpp 复制代码
fork_fd_test:fork_fd_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@

4、execve

exec系列函数可以在同一进程中跳转执行另外一个程序

(1)execve单独使用

cpp 复制代码
//erlou.cpp内容
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char const *argv[])
{
    if (argc < 2)
    {
        printf("参数不够,不能上二楼");
        return 1;
    }
    printf("我是%s 编号%d 父进程编号%d,我跟海哥上二楼了\n",argv[1],getpid(),getpid());
    
    return 0;
}

makefile

cpp 复制代码
erlou:erlou.c
	-$(CC) -o $@ $^
	
cpp 复制代码
//execve_test.cpp内容
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char const *argv[])
{
    //跳转之前
    char *name="banzhang";
    printf("我是%s 编号%d 父进程编号%d,我现在还在一楼\n",name,getpid(),getpid());
    /*
    const char *__path 执行程序的路径
    char *const __argv[] 传入的参数与main函数中argv是对应的
        【1】第一个参数固定是程序的名称
        【2】执行程序需要传入的参数
        【3】最后一个参数一定是NULL
    char *const __envp[] 传递的环境变量
        【1】环境变量参数:key=value
        【2】最后一个参数一定是NULL
    return 成功根本没办法返回 下面的代码没有意义,失败返回 -1
    跳转前后只有进程号保留下来,别的变量都删除了
    int execve(const char *__path, char *const __argv[], char *const __envp[])
    */
    //执行跳转 
    char *args[]={"/home/lxl/process_test/erlou",name,NULL};
    char *envs[]={NULL};
    int re= execve(args[0],args,envs);
    if (re == -1)
    {
        printf("你没有机会上二楼");
        return 1;
    }
    
    //此处的代码没有意义,因为程序跳转了,不会再往下执行了

    return 0;
}
cpp 复制代码
execve_test:execve_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@

(2)execve+fork

可以fork和exec共同使用,实现场景老学员推荐新学员在二楼学习,自己保持不变。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char const *argv[])
{
    //跳转之前
    char *name="banzhang";
    printf("我是%s 编号%d 父进程编号%d,我现在还在一楼\n",name,getpid(),getppid());
    /*
    const char *__path 执行程序的路径
    char *const __argv[] 传入的参数与main函数中argv是对应的
        【1】第一个参数固定是程序的名称
        【2】执行程序需要传入的参数
        【3】最后一个参数一定是NULL
    char *const __envp[] 传递的环境变量
        【1】环境变量参数:key=value
        【2】最后一个参数一定是NULL
    return 成功根本没办法返回 下面的代码没有意义,失败返回 -1
    跳转前后只有进程号保留下来,别的变量都删除了
    int execve(const char *__path, char *const __argv[], char *const __envp[])
    */
    //执行跳转 
    char *args[]={"/home/lxl/process_test/erlou",name,NULL};
    char *envs[]={NULL};
    int re= execve(args[0],args,envs);
    if (re == -1)
    {
        printf("你没有机会上二楼");
        return 1;
    }
    
    //此处的代码没有意义,因为程序跳转了,不会再往下执行了

    return 0;
}

makefile

cpp 复制代码
fork_execve_test:fork_execve_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@

5、waitpid

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main(int argc, char const *argv[])
{
    //fork之前
    int subprocess_status;
    printf("老学员%d在校区\n",getpid());
    pid_t pid = fork();
    if (pid < 0)
    {
        perror("fork");
        return 1;
    }
    else if (pid == 0)
    {
        char* args[]={"/usr/bin/ping","-c","10","www.lxl.com",NULL};
        char*envs[]={NULL};
        printf("新学员%d联系老学员%d 10次\n",getpid(),getppid());
        int exeR = execve(args[0],args,envs);
        if (exeR < 0)
        {
           perror("execve");
           return 1;
        }
    }
    else
    {
        printf("老学员%d等待新学员%d联系\n",getpid(),pid);
        waitpid(pid,&subprocess_status,0);
    }
    printf("老学员等待新学员联系完成\n");
    return 0;
}

makefile

cpp 复制代码
waitpid_test:waitpid_test.c
	-$(CC) -o $@ $^
	-./$@
	-rm ./$@
相关推荐
Shadow(⊙o⊙)15 小时前
进程间通信0.0-pipe()匿名管道,详细分析进程池调度队列执行逻辑,进程池模拟实现。
linux·运维·服务器·开发语言·c++
lcj251115 小时前
【list】【手撕 STL】List 容器全解析!迭代器 / 增删改查 / 去重排序,面试必背的核心考点!
c++·面试·list
指尖的爷15 小时前
C++头文件的作用
开发语言·c++
keykey6.16 小时前
反向传播与梯度下降:神经网络如何学习
开发语言·人工智能·深度学习·机器学习
Jun62616 小时前
QT(5)-第三方日志系统
开发语言·数据库·qt
冰暮流星16 小时前
javascript建立对象之构造函数
开发语言·javascript·ecmascript
keykey6.16 小时前
PyTorch 入门实战:从张量到训练循环
开发语言·人工智能·深度学习·机器学习
智者知已应修善业16 小时前
【51单片机0.1秒计时到21.0时点亮LED】2024-1-5
c++·经验分享·笔记·算法·51单片机
apcipot_rain16 小时前
计科八股20260606——二叉树、PCA、图深度学习、进程上下文、C语言预编译、文件读写、单精度浮点数
c语言·数据结构·算法·pca·图神经网络
消失的旧时光-194316 小时前
Kotlin 协程设计思想(七):为什么 Kotlin 要设计 SupervisorJob 和 supervisorScope?
android·开发语言·kotlin