首页 > 系统相关 >day29 进程基础

day29 进程基础

时间:2024-12-13 19:03:40浏览次数:9  
标签:fork day29 int pid 基础 printf 进程 return

getpid和getppid

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

       pid_t getpid(void);
       功能:调用进程获取自己的ID号
       参数:无
       返回值:成功返回调用进程的ID,没有失败。
       pid_t getppid(void);
       功能:调用进程获取父进程的ID号
       参数:无
       返回值:成功返回调用进程父进程的ID,没有失败。

使用规则

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        printf("父进程中子进程的ID  = %d\n",pid);
        printf("父进程中当前调用进程的ID = %d\n",getpid());

    }
    else if(pid==0)
    {
        printf("子进程中子进程ID = %d\n",getpid());
        printf("子进程中父进程的ID = %d\n",getppid());
    }
    else
    {
        perror("fork");
        return -1;
    }
    while(1);    
    return 0;
}

验证孤儿进程是否有父亲进程的id

孤儿进程的父进程会变成号进程

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        printf("父进程中子进程的ID  = %d\n",pid);
        printf("父进程中当前调用进程的ID = %d\n",getpid());
        exit(0);//成功退出

    }
    else if(pid==0)
    {
        usleep(10);
        printf("子进程中子进程ID = %d\n",getpid());
        printf("子进程中父进程的ID = %d\n",getppid());// 1
    }
    else
    {
        perror("fork");
        return -1;
    }
    while(1);    
    return 0;
}

exit和_exit

#include <stdlib.h>

       void exit(int status);
       功能:进程退出函数,基于标准库,刷新缓冲区后退出。
       参数:进程退出的状态:
       EXIT_SUCCESS(0):成功退出
       EXIT_FAIURE(1):失败退出:
       返回值:无
       #include <unistd.h>

       void _exit(int status);
       功能:进程退出函数,基于系统调用,不刷新缓冲区后退出。
       参数:进程退出的状态:
       EXIT_SUCCESS(0):成功退出
       EXIT_FAIURE(1):失败退出
       返回值:无

使用规则

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid>0)
    {
        printf("元旦快乐");
        exit(0);//成功退出刷新缓冲区退出

    }
    else if(pid==0)
    {
        printf("端午快乐");
        fflush(stdout);//手动刷新缓冲区
        _exit(0);//不刷新缓冲区退出
    }
    else
    {
        perror("fork");
        return -1;
    }
    while(1);    
    return 0;
}

wait和waitpid

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

       pid_t wait(int *wstatus);
        功能:阻塞回收子进程的资源。
        参数:子进程退出时的状态
        返回值:成功回收子进程资源后返回子进程的ID,失败时返回-1.
       pid_t waitpid(pid_t pid, int *wstatus, int options);
       功能:阻塞或者非阻塞回收子进程资源
       参数1:
       >0:回收特定某个子进程资源
       =0:回收当前进程组的所有子进程资源
       =-1:回收任意的子进程资源
       <-1:回收进程组ID等于pid绝对值的所有子进程资源.
        参数2:接收进程退出时的状态一般不接收。
        参数3:
        0:阻塞回收子进程的资源
        WNOHANG:非阻塞回收子进程资源.
        返回值:成功返回回收的进程ID,失败返回-1,但是如果参数3是WNOHANG
        成功后返回0。

使用规则

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid==0)//子进程
    {
        sleep(5);//模拟子进程的执行时间
        printf("我是子进程我要退出了:%d\n",getpid());
        exit(1);//成功退出子进程
    }
    else if(pid>0)//父进程
    {
        //wait(NULL);//阻塞回收子进程的资源
        //waitpid(-1,NULL,0);//阻塞回收子进程的资源
        //waitpid(-1,NULL,WNOHANG);//非阻塞回收
        while(waitpid(-1,NULL,WNOHANG)>0);
        printf("成功回收了子进程的资源\n");//5秒后显示
    }
    else
    {
        perror("fork");
        return -1;
    }
    
    return 0;
}

验证进程的多任务并发执行

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid==0)//子进程
    {
        while(1)
        {
            usleep(1000);
            printf("我是子进程:%d\n",getpid());
        }
    }
    else if(pid>0)//父进程
    {
        while(1)
        {
            usleep(2000);
            printf("我是父进程:%d\n",getpid());
        }
    }
    else
    {
        perror("fork");
        return -1;
    }
    while(1);
    return 0;
}

验证孤儿进程和僵尸进程

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid==0)//子进程
    {
        while(1)
        {
            usleep(1000);//CPU: 0.0004
            printf("我是子进程:%d\n",getpid());
        }
    }
    else if(pid>0)//父进程
    {
        sleep(3);//父进程执行3秒后退出,子进程变成,了孤儿进程
        exit(0);
    }
    else
    {
        perror("fork");
        return -1;
    }
    return 0;
}

子进程退出后子进程修改的数据是否保存

#include <myhead.h>
int main(int argc, const char *argv[])
{
    int k = 1000;

    pid_t pid = fork();
    if(pid==0)//子进程
    {
        sleep(5);
        k+=500;
        printf("我是子进程:%d\tk = %d\n",getpid(),k);//k=1500
    }
    else if(pid>0)//父进程
    {
        waitpid(-1,NULL,0);//阻塞回收子进程资源
        printf("我是父进程,回收完成k = %d\n",k);//k = 1000
    }
    else
    {
        perror("fork");
        return -1;
    }
    printf("最后的语句:k = %d\n",k);//子进程执行时k=1500父进程执行时k=1000
    return 0;
}

创建守护进程

1、创建一个孤儿进程,并修改孤儿进程的操作目录权限为根目录(对根目录某个文件具有读写权限)。

2、将孤儿进程设置为会话组组长,脱离终端独立运行(该孤儿进程变成守护进程)。

3、更改终端下的umask值,以便于创建的文件具有读写执行的全部权限。

4、在根目录下创建一个日志文件。

5、重定向所有的输入输出出错描述符到该日志文件。

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

       pid_t setsid(void);
       功能:设置调用进程为会话组组长。
       参数:无
       返回值:成功返回会话组组长的(新的)ID失败返回-1,并置位错误码。
         #include <unistd.h>

       int chdir(const char *path);
        功能:修改调用进程的工作目录。
        参数:要更改的工作目录
        返回值:成功返回0,失败返回-1,并置位错误码。
        #include <sys/types.h>
       #include <sys/stat.h>

       mode_t umask(mode_t mask);
        功能:更改某个目录下的umask值
        参数:要更改的umask值
        返回值:成功返回旧的umask值,没有失败可言。

创建守护进程

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid = fork();
    if(pid==0)//1、子进程变成了孤儿进程
    {
        setsid();//2、设置孤儿进程为会话组组长
        chdir("/");//3、更改孤儿进程的权限为根目录
        umask(0000);//4、更改终端下的umask值为最小
        int fd = open("./mylog.txt",O_CREAT|O_TRUNC|O_RDWR,0777);
        if(fd==-1)
        {
            perror("open");
            return -1;
        }

        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);
        int i = 0;
        while(i<=1000)//模拟日志文件写入信息
        {
            sleep(1);
            printf("i = %d\n",i);//写入日志文件
            fflush(stdout);
            i++;
        }
    }
    else if(pid>0)
    {
        exit(0);//父进程退出
    }
    else
    {
        perror("fork");
        return -1;
    }
    
    return 0;
}

验证如何创建3个进程

#include <myhead.h>

int main(int argc, const char *argv[])
{
    pid_t pid1 = fork();
    if(pid1==0)
    {
        printf("我是大儿子ID = %d\n",getpid());
        while(1);
    }
    else if(pid1>0)
    {
        printf("我是父进程ID = %d\n",getpid());
        pid_t pid2 = fork();
        if(pid2==0)
        {
            printf("我是二儿子ID  =%d\n",getpid());
            while(1);
        }
        while(1);
    }
    else
    {
        perror("fork");
        return -1;
    }
    return 0;
}

作业:创建3个进程,子进1程拷贝文件的前一半,子进程2拷贝后一半文件,父进程回收两个子进程资源。

#include <luochen.h>

//1、定义子函数,算出源文件的长度返回给主调函数
//2、定义copy函数,参数3个(源文件,目标文件,源文件长度的一半)
int length_file(const char *p1,const char *p2)//计算文件长度
{
    int fd1,fd2;
    fd1 = open(p1,O_RDONLY);//只读方式打开源文件
    if(fd1==-1)
    {
        perror("open");
        return -1;
    }
    int len = lseek(fd1,0,SEEK_END);//算出源文件的长度返回给主调函数
    fd2 = open(p2,O_WRONLY|O_CREAT|O_TRUNC,0664);//创建打开目标文件
    if(fd2==-1)
    {
        perror("open");
        return -1;
    }
    close(fd1);
    close(fd2);
    return len;//返回源文件的长度
}
int copy_file(const char *p1,const char *p2,int start,int half)
{
    int fd1,fd2;
    fd1 = open(p1,O_RDONLY);//只读方式打开源文件
    if(fd1==-1)
    {
        perror("open");
        return -1;
    }
    fd2 = open(p2,O_WRONLY);//只写方式打开目标文件
    if(fd2==-1)
    {
        perror("open");
        return -1;
    }
    lseek(fd1,start,SEEK_SET);
    lseek(fd2,start,SEEK_SET);
    char buff[100];
    int sum=0;
    while(1)
    {
        int res = read(fd1,buff,sizeof(buff));
        sum+=res;//累加求连续读取的字节数
        if(sum>=half||res==0)//子进程和父进程读取到相应位置都要结束
        {
            write(fd2,buff,(res-(sum-half)));
            break;
        }
        write(fd2,buff,res);
    }
    close(fd1);
    close(fd2);
    return 0;
    
}

//创建3个进程,子进程1拷贝文件的前一半,子进程2拷贝后一半文件,父进程回收两个子进程资源


int main(int argc, const char *argv[])
{
	if(argc !=3)
	{
		printf("外部传参错误\n");
		return -1;
	}
	int len = length_file(argv[1],argv[2]);
	pid_t pid1 = fork();
	if(pid1 == 0)
	{
		copy_file(argv[1],argv[2],0,len/2);
        //exit(0);
    }
	else if(pid1 > 0)
	{
		pid_t pid2 = fork();
		if(pid2 == 0)
		{
			copy_file(argv[1],argv[2],len/2,len-len/2);
            //exit(0);		
        }
		while(waitpid(pid1,NULL,WNOHANG)>0);
		while(waitpid(pid2,NULL,WNOHANG)>0);
	}
	else
	{
		perror("fork");
		return -1;
	}
	return 0;
}

标签:fork,day29,int,pid,基础,printf,进程,return
From: https://blog.csdn.net/luochen330x/article/details/144433765

相关文章

  • 转载:【AI系统】GPU 基础
    GPU是GraphicsProcessingUnit(图形处理器)的简称,它是计算机系统中负责处理图形和图像相关任务的核心组件。GPU的发展历史可以追溯到对计算机图形处理需求的不断增长,以及对图像渲染速度和质量的不断追求。从最初的简单图形处理功能到如今的高性能计算和深度学习加速器,GPU经历了......
  • 转载:【AI系统】NPU 基础
    近年来,随着AI技术的飞速发展,AI专用处理器如NPU(NeuralProcessingUnit)和TPU(TensorProcessingUnit)也应运而生。这些处理器旨在加速深度学习和机器学习任务,相比传统的CPU和GPU,它们在处理AI任务时表现出更高的效率和性能。在接下来的内容中,我们将首先简单介绍引入什么是......
  • Java基础面试:可变长参数
    Java中的可变长参数什么是可变参可变参数是在Java5.0中引入的一个特性,是一种语法糖,它允许方法可以接受不定数量的参数,而无需显式地处理数组。在编译时,方法声明中的可变参数会被转换为数组参数,方法调用中的参数会被打包成一个数组。可变参的语法可变参数的语法非常简单,只需......
  • 【百度地图系列教程一】前端html如何快速嵌入百度地图?从基础到进阶功能全面解析完成地
    【百度地图系列教程一】前端html如何快速嵌入百度地图?从基础到进阶功能全面解析完成地图展示功能标签:百度地图、JavaScript、前端开发、WebGL地图、BMapGL前几天,有人让我帮忙实现一个网页,要求能嵌入百度地图,还得支持鼠标滚轮缩放和右键旋转视角。这种需求在展示地理位......
  • 【stablediffusion教程】的基础操作和使用技巧分享
    这是一篇关于stablediffusion本地部署并通过基础模型搭配不同的lora生成图片的教程,软件很容易获取,对电脑的要求也不是太高,相较于本地化的chatglm动不动就要6G显存的门槛还是很低的,根据不同性能显卡,同样的参数生成图片的速度也不一样,4090-24G版本的几秒就可以生成一张图,1060-......
  • 从零开始:PHP基础教程系列-第1篇:PHP简介与环境搭建
    从零开始:PHP基础教程系列第1篇:PHP简介与环境搭建一、PHP简介PHP(全称:PHP:HypertextPreprocessor)是一种广泛使用的开源脚本语言,尤其适合用于Web开发。它可以嵌入HTML中,允许开发者轻松地在网页上动态生成内容。PHP的特点包括:易学易用:PHP的语法相对简单,适合初学者入门。跨......
  • 【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,
    【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,那么大幅遥感影像如何输入到深度学习中进行模型训练呢?patch块的生成,附代码【深度学习|地学应用之遥感图像切块】海量的遥感数据为深度学习的地学应用提供了基础,那么大幅遥感影像如何输入......
  • python基础第六课——字典
    系列文章目录  系列文章目录Python基础学习第一课——python环境的配置及vscode的安装汉化Python基础第二课——基础知识Python基础第三课——条件语句和循环语句Python基础第四课——字符串的相关操作Python基础第五课——列表和元组Python基础第六课——字典(本篇......
  • Windows系统基础(二):本地组与本地安全策略
    本地组和本地安全策略文章目录本地组和本地安全策略1.用户与组概念基本概念:常见组类型:2、用户与组设置常见操作方式:注意事项:3、内置账户控制访问常见内置账户及其功能:账户控制访问配置:4、本地安全组策略组策略的作用:常用的本地安全策略:应用场景:1.用户与组概......
  • Windows系统基础(三):服务端口指南
    服务端口文章目录服务端口一、WEB服务端口二、网络服务端口三、邮件服务端口四、远程服务端口五、其它服务端口总结一、WEB服务端口80(HTTP):HTTP是网站的默认端口,用于明文传输网页内容。虽然速度快,但缺乏加密保护,容易被中间人攻击。443(HTTPS):HTTPS是基于S......