Linux 僵死进程 文件操作

复制进程:fork()

写时拷贝:提高了fork复制的效率

批注 2021-11-30 131711

习题一:

int main()
{
    for(int i=0;i<2;i++)
    {
        fork();
        printf("A\n");

    }
}

打印6个A

父进程 i=0 fork A; i=1 fork A;

批注 2021-11-30 145927

右子进程(i=0 此时从fork后开始执行)A; i=1 fork A

左下子进程(i=1)A;

右下子进程(i=1)A;

批注 2021-11-30 150200

习题二

int main()
{
    for(int i=0;i<2;i++)
    {
        fork();
        printf("A");

    }
}

打印8个A,原本父进程打了一个A,复制的时候,缓存区也会存着A给子进程

父进程 i=0 fork A(缓冲区); i=1 fork A;

批注 2021-11-30 152019

右子进程(i=0 此时从fork后开始执行)A(存在缓冲区); i=1 fork A

左下子进程(i=1)父缓冲区A+A;

右下子进程(i=1)右子缓冲区A+A;

批注 2021-11-30 152132

习题三

int main()
{
     fork()||fork();
     printf("A\n");
}

打印3个A

C语言中||:他会先算前一部分,如果前一部分为真,他将停止运算,如果为假,他才会算第二部分,你这里第一部分就为真了,第二部分当然也就不会算了。

父进程 fork()||fork(); 只执行第一个fork(fork>0),执行后杀死,打印了一个A

子进程 fork()||fork(); 被杀死的第一个fork(==0),因此执行第二个fork(复制出一个子进程),打印一个A

子进程的子进程 fork()||fork(); 被杀死的第一个fork(==0),被杀死第二个fork(==0),打印一个A

批注 2021-11-30 153410

习题四

int main()
{
     fork()&&fork();
     printf("A\n");
}

打印三个A

C语言中:&&且操作 ,&&为界将表达式分为两部分,他会先算前一部分,如果前一部分为假,他将停止运算,如果为真,他才会算第二部分,你这里第一部分就为假了,第二部分当然也就不会算了。

父进程 fork()&&fork(); 执行第一个fork(fork>0),生成子进程1,执行第二个fork,生成子进程2,打印一个A

子进程1 fork()&&fork(); 被杀死的第一个fork(fork==0),不执行第二个fork,打印了一个A

子进程2 fork()&&fork(); 被杀死的第一个fork(fork>0),被杀死的第二个fork(fork==0),打印一个A

批注 2021-11-30 154403

僵死进程

僵死(僵尸)进程:子进程先结束,父进程没有调用wait获取子进程的退出码,子进程就变成了僵死进程

批注 2021-11-30 155322

(PCB没有被删掉)

test.c

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

int main()
{
    int n=0;
    char*s=NULL;
    
    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
        n=3;
        s="child";
    }
    else
    {
        n=10;
        s="parent";
    }

    for(int i=0;i<n;i++)
    {
        printf("s=%s\n",s);
        sleep(1);
    }

    exit(3);
}

后台运行,ps查看->可显示僵死进程

stu@stu-virtual-machine:~/Linux/day08$ ./test&
[1] 3669
stu@stu-virtual-machine:~/Linux/day08$ s=parent
s=child
s=child
s=parent
ps
    PID TTY          TIME CMD
   2550 pts/0    00:00:00 bash
   3669 pts/0    00:00:00 test
   3670 pts/0    00:00:00 test
   3671 pts/0    00:00:00 ps
stu@stu-virtual-machine:~/Linux/day08$ s=child
s=parent
s=parent
s=parent
ps
    PID TTY          TIME CMD
   2550 pts/0    00:00:00 bash
   3669 pts/0    00:00:00 test
   3670 pts/0    00:00:00 test <defunct>
   3672 pts/0    00:00:00 ps
stu@stu-virtual-machine:~/Linux/day08$ s=parent
s=parent
s=parent
s=parent
s=parent

解决方法wait

法一

获得退出码(man 3 wait)

#include<sys/wait.h>
pid_t wait(int *stat loc)

test.c

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

int main()
{
    int n=0;
    char*s=NULL;
    
    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
        n=3;
        s="child";
    }
    else
    {
        n=10;
        s="parent";
        int val=0;
        wait(&val);
        printf("exit_code=%d\n",val);
    }

    for(int i=0;i<n;i++)
    {
        printf("s=%s\n",s);
        sleep(1);
    }

    exit(3);
}

结果

stu@stu-virtual-machine:~/Linux/day08$ ./test
s=child
s=child
s=child
exit_code=768    
s=parent
s=parent
s=parent
s=parent
s=parent
s=parent
s=parent
s=parent
s=parent
s=parent

批注 2021-11-30 162527

768>>8 = 3

法二

image-20211130163408276

判断程序正常结束 获得退出码

test.c

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

int main()
{
    int n=0;
    char*s=NULL;
    
    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
        n=3;
        s="child";
    }
    else
    {
        n=10;
        s="parent";
        int val=0;
        wait(&val);
        if(WIFEXITED(val))//判断程序正常结束
        {
            printf("exit_code=%d\n",WEXITSTATUS(val));//提取退出码
        }
    }

    for(int i=0;i<n;i++)
    {
        printf("s=%s\n",s);
        sleep(1);
    }

    exit(3);
}

结果

stu@stu-virtual-machine:~/Linux/day08$ ./tests=childs=childs=childexit_code=3s=parents=parents=parents=parents=parents=parents=parents=parents=parents=parent

父进程先于子进程结束不是僵死进程

因为子进程在父进程结束后被init接收,init pid=1

test.c

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

int main()
{
    int n=0;
    char*s=NULL;
    
    pid_t pid=fork();
    assert(pid!=-1);

    if(pid==0)
    {
        n=7;
        s="child";
    }
    else
    {
        n=3;
        s="parent";
        /*
        int val=0;
        wait(&val);
        if(WIFEXITED(val))//判断程序正常结束
        {
            printf("exit_code=%d\n",WEXITSTATUS(val));//提取退出码
        }
        */
    }

    for(int i=0;i<n;i++)
    {
        printf("s=%s,pid=%d,ppid=%d\n",s,getpid(),getppid());
        sleep(1);
    }

    exit(3);
}

结果(以前init接管,ppid=1,现在不一定)

stu@stu-virtual-machine:~/Linux/day08$ ./tests=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849s=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849s=child,pid=3850,ppid=3849s=parent,pid=3849,ppid=2550s=child,pid=3850,ppid=3849stu@stu-virtual-machine:~/Linux/day08$ s=child,pid=3850,ppid=1816s=child,pid=3850,ppid=1816s=child,pid=3850,ppid=1816

文件描述符

文件操作

Linux open read write close 系统调用(在内核中实现)

C语言 fopen fread fwrite fclose 库函数(/usr/lib/c.so 在库中实现)

Windows 分 文本文件 和 二进制文件,Linux不区分

man 2 openman 2 readman 2 writeman 2 close

open

int open(const char* pathname, int flags);//用于打开一个已存在的文件int open(const char* pathname, int flags,mode_t mode);//用于新建一个文件,并设置访问权限

pathname:将要打开的文件路径和名称

flags : 打开标志,如 O_WRONLY 只写打开

O_RDONLY 只读打开

O_RDWR 读写方式打开

O_CREAT 文件不存在则创建

O_APPEND 文件末尾追加

O_TRUNC 清空文件,重新写入

mode: 权限 如:“0600”----读写4+2

返回值:为文件描述符

read

ssize_t read(int fd, void* buf, size_t count);

fd 对应打开的文件描述符

buf 存放数据的空间

count 计划一次从文件中读多少字节数据

返回值:为实际读到的字节数

write

ssize_t write(int fd, const void* buf,size_t count);

fd 对应打开的文件描述符

buf 存放待写入的数据

count 计划一次向文件中写多少数据

close

int close(int fd);

fd 要关闭的文件描述符

open.c

#include<stdio.h>#include<sys/types.h>#include<unistd.h>#include<assert.h>#include<stdlib.h>#include<sys/wait.h>#include<fcntl.h>int main(){    int fd=open("file.txt",O_WRONLY|O_CREAT,0600);    assert(fd!=-1);    write(fd,"hello",5);    close(fd);}

结果

stu@stu-virtual-machine:~/Linux/day08$ ./openstu@stu-virtual-machine:~/Linux/day08$ lsfile.txt  main  main.c  open  open.c  test  test.cstu@stu-virtual-machine:~/Linux/day08$ cat file.txthello stu@stu-virtual-machine:~/Linux/day08$ 

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

int main()
{
    int fd=open("file.txt",O_RDONLY);
    assert(fd!=-1);

    char buff[128]={0};
    int n=read(fd,buff,127);//n==0,表示读到了文件末尾
    //只读127防止溢出
    printf("buff=%s\n",buff);

    close(fd);
}

结果

stu@stu-virtual-machine:~/Linux/day08$ ./open
buff=hello

写一个复制图片

open.c

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

int main()
{
    int fdr=open("1.jpg",O_RDONLY);
    int fdw=open("5.jpg",O_WRONLY|O_CREAT,0600);
    if(fdr==-1||fdw==-1)
    {
        return 0;
    }

    char buff[1024]={0};
    int n=0;
    while((n=read(fdr,buff,1024))>0)
    {
        write(fdw,buff,n);
    }

    close(fdr);
    close(fdw);
}

结果

stu@stu-virtual-machine:~/Linux/day08$ ./open
stu@stu-virtual-machine:~/Linux/day08$ ls 
5.jpg     main    open    test
file.txt  main.c  open.c  test.c
stu@stu-virtual-machine:~/Linux/day08$ ls -l
总用量 76
-rw------- 1 stu stu     0 1130 17:53 5.jpg
-rw------- 1 stu stu     5 1130 17:34 file.txt
-rwxrwxr-x 1 stu stu 16736 1130 15:29 main
-rw-rw-r-- 1 stu stu   322 1130 15:29 main.c
-rwxrwxr-x 1 stu stu 16872 1130 17:52 open
-rw-rw-r-- 1 stu stu   743 1130 17:52 open.c
-rwxrwxr-x 1 stu stu 17016 1130 16:43 test
-rw-rw-r-- 1 stu stu   664 1130 16:43 test.c
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值