Linux进程

一、Linux进程
1、什么是进程
进程就是程序的一次运行过程,一个静态的可执行程序a.out的一次运行过程(./a.out从运行到结束)就是一个进程。
(1)、动态过程而不是静态实物
(2)、进程控制块PCB,内核中专门用来管理进程的数据结构。

2、进程ID
(1)getpid、getppid(获取父进程pid)、getuid、getgid、getegid
(2) 实际用户ID和有效用户ID区别(可百度)

3、多进程调度原理
(1)操作系统同时运行多个进程
(2)宏观上的并行和微观上的串行
(3)实际上现代操作系统最小的调度单位是线程而不是进程

4、fork创建子进程
4.1、为什么要创建子进程
(1)每一次程序运行都需要一个进程
(2)多进程实现宏观上的并行

4.2、fork的内部原理
(1)、进程的分裂生长模式。如果操作系统需要一个新的进程来运行一个程序,那么操作系统会用一个现有的进程来复制生成一个新进程。老进程叫做父进程,复制生成的新进程叫做子进程。
(2)fork函数调用一次返回2次,返回值等于0的就是子进程,返回值大于0的就是父进程。
(3)fork的返回值在子进程中等于0,在父进程中等于本次fork创建的子进程的进程ID。
(4)fork的演示

#include<stdio.h>
#include <unistd.h>

int main()
{
   pid_t p1 = -1;
   p1 = fork();

        if(p1 == 0)
        {
                printf("child pid = %d\n",getpid());    //child
        }

        if(p1 >0)
        {
                printf("father pid = %d\n",getpid());   //father
                printf("father p1 = %d\n",p1);
        }

        if(p1<0)
        {
                printf("hello word");   //fork error
        }

//   printf("pid = %d\n",getpid());

 return 0 ;
}
~            

运行结果

CLC@Embed_Learn:~/file$ gcc fork.c
CLC@Embed_Learn:~/file$ ./a.out 
father pid = 3796
father p1 = 3797
child pid = 3797

4.3、关于子进程
(1)子进程与父进程的关系
(2)子进程有自己独立的PCB
(3)子进程被内核同等调度

5、父子进程对文件的操作
5.1、子进程继承父进程中打开的文件
(1)上下文:父进程现open打开一个文件得到fd,然后再fork创建子进程。之后在父子进程中各自write向fd中写入内容。
(2)结果:继续写。实际本质原因是父子进程之间的fd对应的文件指针是被此关联的(很像O_APPEND标志后的样子)

5.2、父子进程各自独自打开同一文件实现共享
(1)父进程open打开1.txt然后写入,子进程打开1.txt然后写入,结论是:分别写。原因是父子进程分离后才各自打开的1.txt,这时候这两个进程的PCB已经独立了,文件表也独立了,因此两次读写是完全独立的。

5.3、总结
(1)父进程在没有fork之前自己做的事对子进程有很大影响,但是父进程fork之后在自己if里做的事情就对子进程没有影响了。本质原因是因为fork内部实际上已经复制父进程的PCB生成了一个新的子进程,并且fork返回时子进程已经完全和父进程脱离并且独立被OS调度执行。
(2)子进程最终目的是要独立去运行另外的程序。

6、进程的诞生和消亡
(1)vfork与fork的区别
1、vfork直接使用父进程的存储空间,不拷贝
2、vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行
(2)进程在运行时需要消耗系统资源(内存,IO),进程终止时应释放这些资源(如果进程消亡后没有释放,那么这些资源就会丢失)
(3)Linux系统设计时规定:每一个进程退出时,操作系统会自动回收这个进程涉及到的所有资源(譬如open打开文件没有close的在程序终止时也会被关闭)。但是操作系统只是回收了这个进程工作时消耗的内存和IO,而并没有回收进程本身占用的内存(8kb,主要是task_struct和栈内存)
(4)因为进程本身的8 kb 内存操作系统不能回收需要别人开辅助回收,因此我们每个进程都需要一个帮助他收尸的人,这个人就是父进程。

(5)僵尸进程
1、子进程先于父进程结束。子进程结束后父进程此时并不一定立即就能帮子进程收尸,在这一段时间,子进程就变成僵尸进程。
2、子进程除task_struct和栈内存外其它内存都以被清理
3、父进程可以使用wait或waitpid以显示回收子进程的剩余待回收的内存资源并且获取子进程的退出状态
4、父进程也可以不使用wait或waitpid回收子进程,此时父进程结束时一样会回收子进程剩余待回收内存资源。(这样设计是为了防止父进程忘记显示调用wait/waitpid来回收子进程从而造成内存泄漏)
(6)孤儿进程
1、父进程先于子进程结束
2、Linux系统规定:所有的孤儿进程都自动成为一个特殊的进程(进程1,也就是init 进程)的子进程。

(7)父进程wait回收子进程
1、wait 的工作原理
(1)子进程结束时,系统向父进程发送SIGCHILO信号
(2)父进程调用wait 函数后阻塞
(3)父进程被SIGCHILO信号唤醒然后去回收僵尸子进程
(4)父子进程之间是异步的,SIGCHILO信号机制就是为了解决父子进程之间的异步通信问题,让父进程及时去回收僵尸子进程
(5)若父进程没有任何子进程则wait返回错误
2、wait的参数status。status是用来返回子进程结束时的状态,父进程通过wait得到status后就可以得知子进程的结束状态。
3、wait的返回值pid_t,就是本次wait回收子进程的PID。当前进程可能有多个子进程,该返回值就可以知道wait回收的是哪个子进程的结束状态信息。
4、总结:wait主要是用来回收子进程资源,回收的同时还可以得知被回收的子进程的PID和退出状态
5、WIFEXITED、WIFSIGNALED、WEXITSTATUS这几个宏用来获取子进程的退出状态
WIFEXITED:用来判断子进程是否正常终止(return,exit,_exit退出)
WIFSIGNALED:用来判断子进程是否非正常终止(被信号所终止)
WEXITSTATUS:用来得到正常终止情况下的进程返回值
6、程序

#include<stdio.h>
#include <sys/types.h>
#include <stdlib.h>
 #include <sys/wait.h>
#include<unistd.h>
int main()
{
     pid_t pid = -1;
     pid = fork();
     pid_t ret = -1;
     int status = -1;

    if(pid > 0)
        {
                //father
                ret = wait(&status);
                printf("child is end ,child pid = %d\n",ret);
                printf("child is ok over:%d\n",WIFEXITED(status));
                printf("child is no  ok over:%d\n",WIFSIGNALED(status));
                printf("child is ok over number:%d\n",WEXITSTATUS(status));
        }

    if(pid == 0)
        {
                //child
          printf("this is child pid:%d\n",getpid());
//          exit(0);
        return 56;
        }
    else
        {
                perror("fork");
                return -1;
        }
return 0;
}

结果

this is child pid:7044
child is end ,child pid = 7044
child is ok over:1
child is no  ok over:0
child is ok over number:56
fork: Success

7、waitpid
pid_t waitpid(pid_t pid, int *status, int options);
可选择指定的子进程进行结束调用,有阻塞于非阻塞两种方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值