int do_exit(long code) { int i; free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); for (i=0 ; i<NR_TASKS ; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ (void) send_sig(SIGCHLD, task[1], 1); } for (i=0 ; i<NR_OPEN ; i++) if (current->filp[i]) sys_close(i); iput(current->pwd); current->pwd=NULL; iput(current->root); current->root=NULL; iput(current->executable); current->executable=NULL; if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; if (last_task_used_math == current) last_task_used_math = NULL; if (current->leader) kill_session(); current->state = TASK_ZOMBIE; current->exit_code = code; tell_father(current->father); schedule(); return (-1); /* just to suppress warnings */ }
int do_exit(long code) { int i; // TODO 待看页表 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); /* * 找出所有子进程,将它们的父亲设为 init 进程,将状态标记为僵尸 * 然后给 init 进程发送一个 SIGCHLD 信号,提醒 init 进程回收子进程 */ for (i=0 ; i<NR_TASKS ; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ // 最后一个参数 1 代表 privilege,此处为强制发送 (void) send_sig(SIGCHLD, task[1], 1); } // TODO 关闭文件? /* * NR_OPEN 是一个进程可以打开的最大文件数 * 而 NR_FILE 是系统在某时刻的限制文件总数 */ for (i=0 ; i<NR_OPEN ; i++) if (current->filp[i]) sys_close(i); // 进程的当前工作目录 inode iput(current->pwd); current->pwd=NULL; // 进程的根目录 inode iput(current->root); current->root=NULL; // 进程本身可执行文件的 inode iput(current->executable); current->executable=NULL; if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; if (last_task_used_math == current) last_task_used_math = NULL; /* * 如果是 session leader 会话领头进程,则向该会话所有进程发送 SIGHUP 信号 * PID, PPID, PGID, SID * http://unix.stackexchange.com/questions/18166/what-are-session-leaders-in-ps * 在同一次 ssh 会话中,用户对应的 shell 最先被启动,成为 session leader, * 所有在同一次会话中产生的进程 session id 都等于这个 session leader 的 pid * 当 session leader 退出时,它会向所有同一 session 中的进程发送 SIGHUP, * 这个信号是可以被捕获的,如果进程忽略这个 SIGHUP,它则可以以一个孤儿进程继续执行 * http://www.firefoxbug.com/index.php/archives/2782/ */ if (current->leader) kill_session(); // 将自己设为僵尸,设置退出状态码,同时告诉父进程回收子进程 current->state = TASK_ZOMBIE; current->exit_code = code; tell_father(current->father); // 如果 tell_father 中找不到父进程,自己把自己释放掉了,那也不会有机会继续执行下面代码了 schedule(); return (-1); /* just to suppress warnings */ }
//// 程序退出处理程序。在系统调用的中断处理程序中被调用。 int do_exit (long code) // code 是错误码。 { int i; // 释放当前进程代码段和数据段所占的内存页(free_page_tables()在mm/memory.c,105 行)。 free_page_tables (get_base (current->ldt[1]), get_limit (0x0f)); free_page_tables (get_base (current->ldt[2]), get_limit (0x17)); // 如果当前进程有子进程,就将子进程的father 置为1(其父进程改为进程1)。如果该子进程已经 // 处于僵死(ZOMBIE)状态,则向进程1 发送子进程终止信号SIGCHLD。 for (i = 0; i < NR_TASKS; i++) if (task[i] && task[i]->father == current->pid) { task[i]->father = 1; if (task[i]->state == TASK_ZOMBIE) /* assumption task[1] is always init */ (void) send_sig (SIGCHLD, task[1], 1); } // 关闭当前进程打开着的所有文件。 for (i = 0; i < NR_OPEN; i++) if (current->filp[i]) sys_close (i); // 对当前进程工作目录pwd、根目录root 以及运行程序的i 节点进行同步操作,并分别置空。 iput (current->pwd); current->pwd = NULL; iput (current->root); current->root = NULL; iput (current->executable); current->executable = NULL; // 如果当前进程是领头(leader)进程并且其有控制的终端,则释放该终端。 if (current->leader && current->tty >= 0) tty_table[current->tty].pgrp = 0; // 如果当前进程上次使用过协处理器,则将last_task_used_math 置空。 if (last_task_used_math == current) last_task_used_math = NULL; // 如果当前进程是leader 进程,则终止所有相关进程。 if (current->leader) kill_session (); // 把当前进程置为僵死状态,并设置退出码。 current->state = TASK_ZOMBIE; current->exit_code = code; // 通知父进程,也即向父进程发送信号SIGCHLD -- 子进程将停止或终止。 tell_father (current->father); schedule (); // 重新调度进程的运行。 return (-1); /* just to suppress warnings */ }
int do_exit() { int i; struct task_struct *p = current; int pid = p->pid; printk("%d\n",pid); for(i = 0;i < NR_PROCESS + NR_PROCS;i++) { if(proc_table[i].parent == pid) { proc_table[i].parent = 1; //init pid if(proc_table[i].state == TASK_WAITING && proc_table[i].state == TASK_ZOMBIE) { // release_process(&proc_table[i]); } } } p->state = TASK_ZOMBIE; // p->exit_code = code; tell_father(p->parent); schedule(); return 0; }
int main(int argc, char const *argv[]) { char buf[MAXSIZE]={'\0'}; char buf_r[MAXSIZE]={'\0'}; int fd[2]; pipe(fd); signal(SIGPIPE,fun); pid_t pid; int len = 0; int nr = 0; int sum = 0; int nread,len_r; //signal tongbu tell_wait(); //sgnal tongbu pid = fork(); if (pid <0) { perror("error"); /* code */ }else if (pid == 0) { /* code */ wait_father(); printf("the child process.....%d\n",getpid()); printf("the child process's father process id:%d\n",getppid()); close(fd[1]); while((nread = read(fd[0],buf,sizeof(buf)))!=-1){ tell_father(pid); setbuf(stdout,NULL);//set the stdout no buffer printf("the child write to stdout:"); write(STDOUT_FILENO,buf,nread); //the write to stdout is bo bug ,but the printf is bug len_r = strlen(buf); printf("len_r :%d\n",len_r ); for (int i = 0; (buf[i]!='\n'); i++) { sum +=i; printf("sum:%d\n",sum ); printf("buf[%d]:%c\t",i,buf[i] ); if (buf[i]=='\0') { break; } } printf("\n"); // printf("child read:%s\n",buf ); //the sentence is bug ,it is of buffer and \n } exit(0); }else{ // sleep(3); tell_child(pid); printf("the father process.......%d\n",getpid()); printf("the father process's father process id:%d\n",getppid()); close(fd[0]);//the sentense to invlole the SIGPIPE take place char * p = NULL; /* code */ while((p = fgets(buf,sizeof(buf),stdin))!=NULL){ len = strlen(buf); printf("the length :%d\n",len ); if (p[len] =='\n') { printf("%c\n",p[len -1] ); len--; p[len ] = '\0'; /* code */ } if (p[len -1] == '\0') { printf("fgets read the null in buffer\n"); /* code */ } fflush(stdin); int n = write(fd[1],buf,len); if (n==-1) { if (errno = EINTR) { printf("the failed is SIGINT\n"); /* code */ } printf("err write\n"); }else printf("father write to pipe successfully\n"); wait_child(); } int status; // the waitpid 's return val is the son process pid,if it wait to catch the son state successfully int ret = waitpid(pid,&status,0); if (ret == -1) { printf("wait child failed\n"); /* code */ }else printf("the wait id:%d\n", ret);//the ret == son pid } return 0; }