day29 进程基础

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值