进程详解和fork复制

 进程

进程:一个正在执行的程序,为了方便操作系统管理,每个进程都有一个PCB(进程控制块),在Linux中称之为进程描述符,通过进程控制块PCB,struct tast_struct结构体来记录进程的信息。进程的信息宝库,进程标识符pid,优先级,进程状态,程序计数器,程序上下文,信号等等。

进程的状态:就绪态,运行态,阻塞太

       就绪:所有资源都已将准备完成,等待cpu的调用

       阻塞:等待某些时间的发生,时间未发生前,不能被cpu调度

       运行:在cpu上正在执行

       就绪->运行:一切所需要的资源准备好,系统进行调度

       运行->就绪:分配给进进程的时间片用完

       运行->阻塞:需要某些事件的发生才能运行

       阻塞->运行:等待的事件已经发生,只能转到就绪态,不能直接转到运行态,还需要等待cpu的调度。

将死进程:子进程先于父进程结束,而父进程没有获取到子进程的状态信息。

解决方法:对子进程的退出捕获他们的退出信号SIGCHLD,父进程在接收到退出信号时,调用wait()waitpid()函数来释放子进程的资源。还有一种解决方法,就是在父进程调用signal来忽略退出信号SIGCHLD,这样子进程结束后会由内核释放子进程的资源。

面试问题

1.进程和线程的区别

 地址空间:同一进程的线程共享本进程的地址空间,而进程和进程之间是独立的地址空间。

资源享有:同一进程内的线程共享本进程的资源,如内存,I/O等等,但是进程之间的资源是独立的。

健壮性:一个进程在崩溃后在保护模式下不会对其他进程产生影响,但是一个线程奔溃后整个进程都会死掉,所以多进程要比多线程健壮。

消耗:进程切换时,消耗的资源大,效率低。所以设计到频繁的切换时,使用多线程比多进程好。同样如果要求同时进行并且又要共享某些变量的并发操作,线程比进程好。

线程是程序执行的最小单位,进程是资源分配的最小单位。

两者均可以并发执行。

2. fork()进程复制的流程

当fork()函数被调用时,内核就会为新进程创建各种数据结构,并分配给该进程一个唯一的pid。子进程和父进程用的是相同的内存空间,也就是说子进程的代码段,数据段,堆栈都是指向父进程的物理空间,两者的虚拟空间不同,但是对应的相同的物理空间。当父子进程中有更改相应段的操作发生时,系统会给子进程分配物理空间。这就是写时拷贝。

fork()函数调用一次,返回两次,三种返回值

       1. 父进程中的返回值是子进程的pid

       2. 子进程中fork成功的话返回值为0,失败的话返回值是-1 

注意:子进程和父进程访问变量的值却不改变变量的值,相当于读取了一下,这个时候不会给子进程分配新的资源,而是接着共享父进程的资源。但是当系统发现子进程或者父进程要该表某一变量的值的时候,系统就会给子进程分配心的内存空间,然后子进程将父进程中fork之前的变量拷贝一份,此时此刻,子进程和父进程的内存空间已经不同了。写时拷贝是以“页”为单位复制的。

3. 系统最多可以运行多少进程?为什么?

每一个系统能够运行进程数量不同,可以通过ulimit -u来查看我们自己的系统中的进程上线。当然这是可以改变的。通过ulimit -u 数值来改变。我们用pid_t来表示进程的pid,能表示的进程范围一定不会超过pid_t类型的大小,通多命令:cat/proc/sys/kernel/pid_max 来查看最大进程数。查到的数值是32768,这只是一个理论值,实际上由于内存等系统资源的的限制,根本不会同时有这么多的进程存在,并且进程pid是从300往上申请的,因为系统的程序需要占用许多pid。

关于fork的笔试题


int main()
{

    fork() || fork();
    printf("A\n");
}

打印3个A,第一个fork执行之后,父进程打印一个A,但是子进程中返回值是0,第一个fork假,执行第二个fork,子进程再fork出一个子进程,所以两个子进程打印两个A。所以一共3个A
int main()
{
    printf("A");
    write(1,"B",1);
    fork();
}

打印BAA,printf("A"),没有\n,所以这个A在main函数的缓冲区中,write系统调用,直接将B打印在屏幕上,
fork之后,复制了一份缓冲区中的A,现在缓冲区中两个A,系统结束之后,将缓冲区中的两个A全部打印咱屏幕上


 


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

打印6个A
int main()
{
    int i = 0;
    for(;i < 2;i++)
    {	
	fork();
	printf("A");
    }
}
打印8个A

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值