欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

Linux内核 ——进程管理之进程诞生(基于版本4.x)

程序员文章站 2022-03-15 10:15:33
《奔跑吧linux内核》3.1笔记,不足之处还望大家批评指正 进程是Linux内核最基本的抽象之一,它是处于执行期的程序。它不仅局限于一段可执行代码(代码段),还包括进程需要的其他资源。在Linux内核中常被称作任务。 线程被称为轻量级进程,是操作系统调度的最小单元,通常一个进程可以拥有多个线程。 ......

《奔跑吧linux内核》3.1笔记,不足之处还望大家批评指正

进程是linux内核最基本的抽象之一,它是处于执行期的程序。它不仅局限于一段可执行代码(代码段),还包括进程需要的其他资源。在linux内核中常被称作任务。

线程被称为轻量级进程,是操作系统调度的最小单元,通常一个进程可以拥有多个线程。

进程和线程的区别在于进程拥有独立的资源空间,而线程则共享进程的资源空间。

问题一:在内核中如何获取当前进程的task_struct数据结构?

  内核有一个常用的常量current用于获取当前进程task_struct数据结构,它利用了内核栈的特性。首先通过sp寄存器获取当前内核栈的地址,对齐后获取struct thread_info数据结构指针,最后通过thread_info->task成员获取task_struct数据结构。图1为linux内核栈的结构图。

Linux内核 ——进程管理之进程诞生(基于版本4.x)图1 内核栈

 

问题二:下面程序会打印几个“_”?

int main(void){

  int i;

  for(i=0; i<2; i++){

    fork();

    printf("_\n");}

  wait(null);wait(null);

  return 0;}

   答案是6个“_”,具体思路如图2所示。(i=0,调用一次fork后,父进程a创建子进程b,此后a和b进行打印,打印两个“_”;后i=1,a和b均调用fork,a创建子进程a_1,b创建子进程b_1,4个进程执行打印操作,打印出四个“_”;i=2,返回)

Linux内核 ——进程管理之进程诞生(基于版本4.x)图2 fork解题思路

 

问题三:用户空间进程的页表是什么时候分配的,其中一级页表什么时候分配?二级页表呢?

   (此问有点疑问,暂且认为一级页表为页目录项(pgd),二级页表为也表项(pte))

  对于内核来说,进程的“鼻祖”是idle进程,称为swapper进程;对于用户空间来说,进程“鼻祖”是init进程,所有用户空间进程都由init进程创建或派生。

  在mm_init()函数中,首先给新进程的mm_struct数据结构进行初始化,然后对mm_users,mm_count进行初始化,设置进程空间地址读写信号量,设置保护进程页表的spinlock锁,最后调用pgd_alloc()函数进行pgd页表的分配工作。在pgd_alloc()函数中,调用pte_alloc_map()函数进行第0,第1个页表的分配,此后在dup_mmap()函数中将父进程所有的vma对应的pte页表项复制到子进程对应的pte页表项中。

问题四:请简述fork,vfork和clone之间的区别?

   fork,vfork,clone的实现都是通过调用do_fork()函数实现的,只是函数调用不一样。

  fork函数实现:do_fork(sigchld,0,0,null,null);只使用sigchld标志位,在子进程终止后发送sigchld信号通知父进程。fork是重量级调用,为子进程建立了一个基于父进程的完整副本,然后子进程基于此运行。为了减少工作量采用写时复制技术(cow),子进程只复制父进程的页表,不复制页面内容。当子进程需要写入新内容时,才触发写时复制机制,为子进程创建一个副本。

  vfork函数实现:do_fork(clone_vfork | clone_vm | sigchld,0,0,null,null);它比fork多了两个标志位,分别为clone_vfork和clone_vm。clone_vfork表示父进程会被挂起,直至子进程释放虚拟内存资源。clone_vm表示父子进程运行在相同的内存空间中。

  clone函数实现:do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);clone用于创建线程,并且参数通过寄存器从用户空间传递下来,通常会指定新的栈地址(newsp)。