• day6:操作系统进程销毁


    syscall_

    do_xxx 这两个基本上都是中断调用

    1.内核的销毁流程

            1.1exit是销毁函数-----一个系统调用----do_exit

                    首先该函数会释放进程的代码段和数据段占用的内存

            1.2 关闭进程打开的所有文件,对当前的目录和i节点进行同步(文件操作)

            1.3 如果当前要销毁的进程有子进程,那么就让1号进程作为新的父进程(init进程)

            1.4 如果当前进程是一个会话头进程,则终止会话中的所有进程

            1.5 改变当前进程的运行状态,变成僵死状态,并且向其父进程发送SIGCHLD信号

            

            2.1 父进程在运行子进程的时候 一般都会运行wait或wait_pid函数(父进程等待某个子进程终止) 当父进程收到SIGCHLD信号时,父进程会终止僵死状态的子进程

            2.2首先父进程会把子进程的运行时间累加到自己进程变量中

            2.3把对应的子进程的进程描述结构体进行释放,置空任务数组中的空槽

    清空任务描述表中的对应进程表项,释放对应的内存页(数据段 代码段 堆栈)

    void release(struct task_struct * p);

    给指定的进程p发送对应的sig信号

    static inline int send_sig(long sig,struct task_struct * p,int priv)

    终止会话,终止当前进程的会话,给其发送SIGHUP

    static void kill_session(void)

    给指定进程发送信号

    int sys_kill(int pid,int sig)

    pid     {

                    pid>0  给对应的pid发送sig

                    pid=0 给对应进程的进程组发送sig

                    pid=-1 给所有进程发送

                    pid<-1 给进程组号为-pid的进程组发送信号

             }

    1. int sys_kill(int pid,int sig)
    2. {
    3. struct task_struct **p = NR_TASKS + task;
    4. int err, retval = 0;
    5. //pid=0,给当前进程组发送信号
    6. if (!pid) while (--p > &FIRST_TASK) {
    7. if (*p && (*p)->pgrp == current->pid)
    8. if (err=send_sig(sig,*p,1))
    9. retval = err;
    10. }
    11. //pid>0 给指定进程发送信号
    12. else if (pid>0) while (--p > &FIRST_TASK) {
    13. if (*p && (*p)->pid == pid)
    14. if (err=send_sig(sig,*p,0))
    15. retval = err;
    16. }
    17. //pid=-1,给所有进程发送信号
    18. else if (pid == -1) while (--p > &FIRST_TASK)
    19. if (err = send_sig(sig,*p,0))
    20. retval = err;
    21. //pid<-1,给进程组号为-pid的进程组发送信号
    22. else while (--p > &FIRST_TASK)
    23. if (*p && (*p)->pgrp == -pid)
    24. if (err = send_sig(sig,*p,0))
    25. retval = err;
    26. return retval;
    27. }

    int do_exit(long code):

    1. int do_exit(long code)
    2. {
    3. int i;
    4. //tag 释放当前的内存页 tss段和ldt段
    5. free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
    6. free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
    7. for (i=0 ; i
    8. //tag 当前要关闭的进程是某个进程的父进程
    9. if (task[i] && task[i]->father == current->pid) {
    10. task[i]->father = 1;
    11. if (task[i]->state == TASK_ZOMBIE)
    12. /* assumption task[1] is always init */
    13. (void) send_sig(SIGCHLD, task[1], 1);
    14. }
    15. //tag 关闭当前进程打开的文件
    16. for (i=0 ; i
    17. if (current->filp[i])
    18. sys_close(i);
    19. //tag 文件操作
    20. iput(current->pwd);
    21. current->pwd=NULL;
    22. iput(current->root);
    23. current->root=NULL;
    24. iput(current->executable);
    25. current->executable=NULL;
    26. //tag 如果使用了终端
    27. if (current->leader && current->tty >= 0)
    28. tty_table[current->tty].pgrp = 0;
    29. //tag 如果使用协处理器
    30. if (last_task_used_math == current)
    31. last_task_used_math = NULL;
    32. //tag 如果是会话头进程
    33. if (current->leader)
    34. kill_session();
    35. //tag 将状态设为僵死状态
    36. current->state = TASK_ZOMBIE;
    37. current->exit_code = code;
    38. //tag 向父进程发送SIGCHLD
    39. tell_father(current->father);
    40. //tag 重新调度进程
    41. schedule();
    42. return (-1); /* just to suppress warnings */
    43. }

    int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); 

    1. int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
    2. {
    3. int flag, code;
    4. struct task_struct ** p;
    5. verify_area(stat_addr,4);
    6. repeat:
    7. flag=0;
    8. for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
    9. if (!*p || *p == current)
    10. continue;
    11. if ((*p)->father != current->pid)
    12. continue;
    13. if (pid>0) {
    14. if ((*p)->pid != pid)
    15. continue;
    16. } else if (!pid) {
    17. if ((*p)->pgrp != current->pgrp)
    18. continue;
    19. } else if (pid != -1) {
    20. if ((*p)->pgrp != -pid)
    21. continue;
    22. }
    23. switch ((*p)->state) {
    24. case TASK_STOPPED:
    25. if (!(options & WUNTRACED))
    26. continue;
    27. put_fs_long(0x7f,stat_addr);
    28. return (*p)->pid;
    29. case TASK_ZOMBIE:
    30. current->cutime += (*p)->utime;
    31. current->cstime += (*p)->stime;
    32. flag = (*p)->pid;
    33. code = (*p)->exit_code;
    34. release(*p);
    35. put_fs_long(code,stat_addr);
    36. return flag;
    37. default:
    38. flag=1;
    39. continue;
    40. }
    41. }
    42. if (flag) {
    43. if (options & WNOHANG)
    44. return 0;
    45. current->state=TASK_INTERRUPTIBLE;
    46. schedule();
    47. if (!(current->signal &= ~(1<<(SIGCHLD-1))))
    48. goto repeat;
    49. else
    50. return -EINTR;
    51. }
    52. return -ECHILD;
    53. }

  • 相关阅读:
    毕业设计 基于单片机的智能盲人头盔系统 - 导盲杖 stm32
    桂林电子科技大学计算机考研资料汇总
    停更的公众号
    OpenHarmony SystemUI开发记录
    数据库管理工具Navicat16版本,功能优化全新详解
    剑指 Offer II 013. 二维子矩阵的和(Java)
    非母语玩家如何撰写研究性英文论文:0. 前言
    【数据结构】AVL树
    MyBatis的映射器语法
    《回炉重造》——泛型
  • 原文地址:https://blog.csdn.net/weixin_66218530/article/details/134072846