久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Linux 內(nèi)核

 風(fēng)之library 2014-12-31

本文分析基于Linux 0.11內(nèi)核,轉(zhuǎn)載請(qǐng)表明出處http://blog.csdn.net/yming0221/archive/2011/06/05/6527337.aspx

Linux在move_to_user_mode()之后,,進(jìn)程0通過fork()產(chǎn)生子進(jìn)程實(shí)際就是進(jìn)程1(init進(jìn)程),。

其中fork()是通過內(nèi)嵌匯編的形式給出

  1. #define _syscall0(type,name) /   
  2. type name(void) /  
  3. { /  
  4. long __res; /  
  5. __asm__ volatile ( "int $0x80" /    // 調(diào)用系統(tǒng)中斷0x80。   
  6. :"=a" (__res) /     // 返回值??eax(__res),。   
  7. :"0" (__NR_##name)); /           // 輸入為系統(tǒng)中斷調(diào)用號(hào)__NR_name,。   
  8.       if (__res >= 0) /      // 如果返回值>=0,則直接返回該值,。   
  9.       return (type) __res; errno = -__res; /    // 否則置出錯(cuò)號(hào),,并返回-1。   
  10.       return -1;}  

 

這樣使用int 0x80中斷,調(diào)用sys_fork系統(tǒng)調(diào)用來創(chuàng)建進(jìn)程,。詳細(xì)過程如下:

系統(tǒng)在sched.c中sched_init()函數(shù)最后設(shè)置系統(tǒng)調(diào)用中斷門

set_system_gate (0x80, &system_call);

設(shè)置系統(tǒng)調(diào)用的中斷號(hào),。

通過int 0x80調(diào)用sys_fork()

其使用匯編實(shí)現(xiàn)

系統(tǒng)將堆棧的內(nèi)容入棧,然后執(zhí)行call _sys_call_table(,%eax,4)

調(diào)用地址 = _sys_call_table + %eax * 4

然后真正調(diào)用sys_fork()

  1. _sys_fork:  
  2. call _find_empty_process # 調(diào)用find_empty_process()(kernel/fork.c,135),。  
  3. testl %eax,%eax  
  4. js 1f  
  5. push %gs  
  6. pushl %esi  
  7. pushl %edi  
  8. pushl %ebp  
  9. pushl %eax  
  10. call _copy_process # 調(diào)用C 函數(shù)copy_process()(kernel/fork.c,68),。  
  11. addl $20,%esp # 丟棄這里所有壓棧內(nèi)容。  
  12. 1: ret  

 

然后調(diào)用find_empty_process()

  1. int find_empty_process (void)  
  2. {  
  3.   int i;  
  4. repeat:  
  5.   if ((++last_pid) < 0)  
  6.     last_pid = 1;  
  7.   for (i = 0; i < NR_TASKS; i++)  
  8.     if (task[i] && task[i]->pid == last_pid)  
  9.       goto repeat;  
  10.   for (i = 1; i < NR_TASKS; i++) // 任務(wù)0 排除在外,。   
  11.     if (!task[i])  
  12.       return i;  
  13.   return -EAGAIN;  
  14. }  

 

該函數(shù)設(shè)置last_pid為最后可用不重復(fù)的pid號(hào),,然后返回task[]數(shù)組中空閑的項(xiàng)的index,存放在EAX中。

再將相應(yīng)的寄存器 入棧,,作為C函數(shù)的參數(shù),,調(diào)用copy_process()

  1. int  
  2. copy_process (int nr, long ebp, long edi, long esi, long gs, long none,  
  3.           long ebx, long ecx, long edx,  
  4.           long fs, long es, long ds,  
  5.           long eip, long cs, long eflags, long esp, long ss)  
  6. {  
  7.   struct task_struct *p;  
  8.   int i;  
  9.   struct file *f;  
  10.   p = (struct task_struct *) get_free_page ();  // 為新任務(wù)數(shù)據(jù)結(jié)構(gòu)分配內(nèi)存。   
  11.   if (!p)           // 如果內(nèi)存分配出錯(cuò),,則返回出錯(cuò)碼并退出,。   
  12.     return -EAGAIN;  
  13.   task[nr] = p;         // 將新任務(wù)結(jié)構(gòu)指針放入任務(wù)數(shù)組中。   
  14. // 其中nr 為任務(wù)號(hào),,由前面find_empty_process()返回,。   
  15.   *p = *current;        /* NOTE! this doesn't copy the supervisor stack */  
  16. /* 注意!這樣做不會(huì)復(fù)制超級(jí)用戶的堆棧 */ (只復(fù)制當(dāng)前進(jìn)程內(nèi)容),。  
  17.     p->state = TASK_UNINTERRUPTIBLE; // 將新進(jìn)程的狀態(tài)先置為不可中斷等待狀態(tài),。   
  18.   p->pid = last_pid;     // 新進(jìn)程號(hào)。由前面調(diào)用find_empty_process()得到,。   
  19.   p->father = current->pid;   // 設(shè)置父進(jìn)程號(hào),。   
  20.   p->counter = p->priority;  
  21.   p->signal = 0;     // 信號(hào)位圖置0。   
  22.   p->alarm = 0;  
  23.   p->leader = 0;     /* process leadership doesn't inherit */  
  24. /* 進(jìn)程的領(lǐng)導(dǎo)權(quán)是不能繼承的 */  
  25.   p->utime = p->stime = 0;    // 初始化用戶態(tài)時(shí)間和核心態(tài)時(shí)間,。   
  26.   p->cutime = p->cstime = 0;  // 初始化子進(jìn)程用戶態(tài)和核心態(tài)時(shí)間,。   
  27.   p->start_time = jiffies;   // 當(dāng)前滴答數(shù)時(shí)間。   
  28. // 以下設(shè)置任務(wù)狀態(tài)段TSS 所需的數(shù)據(jù)(參見列表后說明),。   
  29.   p->tss.back_link = 0;  
  30.   p->tss.esp0 = PAGE_SIZE + (long) p;    // 堆棧指針(由于是給任務(wù)結(jié)構(gòu)p 分配了1 頁   
  31. // 新內(nèi)存,,所以此時(shí)esp0 正好指向該頁頂端)。   
  32.   p->tss.ss0 = 0x10;     // 堆棧段選擇符(內(nèi)核數(shù)據(jù)段)[??],。   
  33.   p->tss.eip = eip;      // 指令代碼指針,。   
  34.   p->tss.eflags = eflags;    // 標(biāo)志寄存器。   
  35.   p->tss.eax = 0;  
  36.   p->tss.ecx = ecx;  
  37.   p->tss.edx = edx;  
  38.   p->tss.ebx = ebx;  
  39.   p->tss.esp = esp;  
  40.   p->tss.ebp = ebp;  
  41.   p->tss.esi = esi;  
  42.   p->tss.edi = edi;  
  43.   p->tss.es = es & 0xffff;   // 段寄存器僅16 位有效,。   
  44.   p->tss.cs = cs & 0xffff;  
  45.   p->tss.ss = ss & 0xffff;  
  46.   p->tss.ds = ds & 0xffff;  
  47.   p->tss.fs = fs & 0xffff;  
  48.   p->tss.gs = gs & 0xffff;  
  49.   p->tss.ldt = _LDT (nr);    // 該新任務(wù)nr 的局部描述符表選擇符(LDT 的描述符在GDT 中),。   
  50.   p->tss.trace_bitmap = 0x80000000;  
  51. // 如果當(dāng)前任務(wù)使用了協(xié)處理器,,就保存其上下文,。   
  52.     if (last_task_used_math == current)  
  53.     __asm__ ("clts ; fnsave %0"::"m" (p->tss.i387));  
  54. // 設(shè)置新任務(wù)的代碼和數(shù)據(jù)段基址、限長(zhǎng)并復(fù)制頁表。如果出錯(cuò)(返回值不是0),,則復(fù)位任務(wù)數(shù)組中   
  55. // 相應(yīng)項(xiàng)并釋放為該新任務(wù)分配的內(nèi)存頁,。   
  56.   if (copy_mem (nr, p))  
  57.     {               // 返回不為0 表示出錯(cuò)。   
  58.       task[nr] = NULL;  
  59.       free_page ((long) p);  
  60.       return -EAGAIN;  
  61.     }  
  62. // 如果父進(jìn)程中有文件是打開的,,則將對(duì)應(yīng)文件的打開次數(shù)增1,。   
  63.   for (i = 0; i < NR_OPEN; i++)  
  64.     if (f = p->filp[i])  
  65.       f->f_count++;  
  66. // 將當(dāng)前進(jìn)程(父進(jìn)程)的pwd, root 和executable 引用次數(shù)均增1。   
  67.   if (current->pwd)  
  68.     current->pwd->i_count++;  
  69.   if (current->root)  
  70.     current->root->i_count++;  
  71.   if (current->executable)  
  72.     current->executable->i_count++;  
  73. // 在GDT 中設(shè)置新任務(wù)的TSS 和LDT 描述符項(xiàng),,數(shù)據(jù)從task 結(jié)構(gòu)中取,。   
  74. // 在任務(wù)切換時(shí),任務(wù)寄存器tr 由CPU 自動(dòng)加載,。   
  75.   set_tss_desc (gdt + (nr << 1) + FIRST_TSS_ENTRY, &(p->tss));  
  76.   set_ldt_desc (gdt + (nr << 1) + FIRST_LDT_ENTRY, &(p->ldt));  
  77.   p->state = TASK_RUNNING;   /* do this last, just in case */  
  78. /* 最后再將新任務(wù)設(shè)置成可運(yùn)行狀態(tài),,以防萬一 */  
  79.   return last_pid;      // 返回新進(jìn)程號(hào)(與任務(wù)號(hào)是不同的)。   
  80. }  

 

這段代碼的執(zhí)行內(nèi)容是:首先為進(jìn)程分配內(nèi)存,,然后將新任務(wù)的指針放入上步查到的空閑task[]數(shù)組項(xiàng)中,,然后復(fù)制父進(jìn)程的內(nèi)容后修改當(dāng)前

進(jìn)程的一部分屬性和tss(任務(wù)狀態(tài)段),最后設(shè)置新進(jìn)程的代碼段和數(shù)據(jù)段,,限長(zhǎng),,在GDT 中設(shè)置新任務(wù)的TSS 和LDT 描述符項(xiàng),數(shù)據(jù)從task 結(jié)構(gòu)中取,。在任務(wù)切換時(shí),,任務(wù)寄存器tr 由CPU 自動(dòng)加載。

  set_tss_desc (gdt + (nr << 1) + FIRST_TSS_ENTRY, &(p->tss));

  set_ldt_desc (gdt + (nr << 1) + FIRST_LDT_ENTRY, &(p->ldt));

  p->state = TASK_RUNNING;

這樣,,新進(jìn)程就創(chuàng)建完畢了,。

其中復(fù)制頁表函數(shù)copy_mem()待續(xù).......

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多