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的进程组发送信号

         }

int sys_kill(int pid,int sig)
{
	struct task_struct **p = NR_TASKS + task;
	int err, retval = 0;
    //pid=0,给当前进程组发送信号
	if (!pid) while (--p > &FIRST_TASK) {
		if (*p && (*p)->pgrp == current->pid) 
			if (err=send_sig(sig,*p,1))
				retval = err;
	}
    //pid>0 给指定进程发送信号 
    else if (pid>0) while (--p > &FIRST_TASK) {
		if (*p && (*p)->pid == pid) 
			if (err=send_sig(sig,*p,0))
				retval = err;
	}
    //pid=-1,给所有进程发送信号 
    else if (pid == -1) while (--p > &FIRST_TASK)
		if (err = send_sig(sig,*p,0))
			retval = err; 
    //pid<-1,给进程组号为-pid的进程组发送信号
	else while (--p > &FIRST_TASK)
		if (*p && (*p)->pgrp == -pid)
			if (err = send_sig(sig,*p,0))
				retval = err;
	return retval;
}

int do_exit(long code):

int do_exit(long code)
{
	int i;
//tag 释放当前的内存页 tss段和ldt段
	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 ; ifather == 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);
		}
	//tag 关闭当前进程打开的文件
	for (i=0 ; ifilp[i])
			sys_close(i);
	//tag 文件操作
	iput(current->pwd);
	current->pwd=NULL;
	iput(current->root);
	current->root=NULL;
	iput(current->executable);
	current->executable=NULL;
	//tag 如果使用了终端
	if (current->leader && current->tty >= 0)
		tty_table[current->tty].pgrp = 0;
	//tag 如果使用协处理器
	if (last_task_used_math == current)
		last_task_used_math = NULL;
	//tag 如果是会话头进程
	if (current->leader)
		kill_session();
	//tag 将状态设为僵死状态
	current->state = TASK_ZOMBIE;
	current->exit_code = code;
	//tag 向父进程发送SIGCHLD
	tell_father(current->father);
	//tag 重新调度进程
	schedule();
	return (-1);	/* just to suppress warnings */
}

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

int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
{
	int flag, code;
	struct task_struct ** p;

	verify_area(stat_addr,4);
repeat:
	flag=0;
	for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
		if (!*p || *p == current)
			continue;
		if ((*p)->father != current->pid)
			continue;
		if (pid>0) {
			if ((*p)->pid != pid)
				continue;
		} else if (!pid) {
			if ((*p)->pgrp != current->pgrp)
				continue;
		} else if (pid != -1) {
			if ((*p)->pgrp != -pid)
				continue;
		}
		switch ((*p)->state) {
			case TASK_STOPPED:
				if (!(options & WUNTRACED))
					continue;
				put_fs_long(0x7f,stat_addr);
				return (*p)->pid;
			case TASK_ZOMBIE:
				current->cutime += (*p)->utime;
				current->cstime += (*p)->stime;
				flag = (*p)->pid;
				code = (*p)->exit_code;
				release(*p);
				put_fs_long(code,stat_addr);
				return flag;
			default:
				flag=1;
				continue;
		}
	}
	if (flag) {
		if (options & WNOHANG)
			return 0;
		current->state=TASK_INTERRUPTIBLE;
		schedule();
		if (!(current->signal &= ~(1<<(SIGCHLD-1))))
			goto repeat;
		else
			return -EINTR;
	}
	return -ECHILD;
}

你可能感兴趣的:(linux内核,linux,运维,服务器)