📄 exit.c
字号:
/* MShowTec - www.mshowtec.com
** msLinux exit.c ver1.0
** 20051221 lmjx create limiao@mshowtec.com
**
*/
#define MSLINUX_EXIT_C
#include "signal.h"
#include "sched.h"
#include "wait.h"
#include "errno.h"
#include "kernel.h"
#include "malloc.h"
void release (struct task_struct *p)
{
int i;
if (!p)
return;
for (i = 1; i < NR_TASKS; i++)
if (task[i] == p)
{
task[i] = NULL;
free((void*)(p->stack.p_TopOfStack));
free((void*)p);
schedule ();
return;
}
panic ("trying to release non-existent task");
}
static __inline int send_sig (long sig, struct task_struct *p,int priv)
{
if (!p || sig < 1 || sig > 32)
return -EINVAL;
if (priv || (current->euid == p->euid) || suser ())
p->signal |= (1 << (sig - 1));
else
return -EPERM;
return 0;
}
static void kill_session (void)
{
struct task_struct **p = NR_TASKS + task;
while (--p > &FIRST_TASK)
{
if (*p && (*p)->session == current->session)
(*p)->signal |= 1 << (SIGHUP - 1);
}
}
int sys_kill (int pid, int sig)
{
struct task_struct **p = NR_TASKS + task;
int err, retval = 0;
if (!pid)
while (--p > &FIRST_TASK)
{
if (*p && (*p)->pgrp == current->pid)
if (err = send_sig (sig, *p, 1))
retval = err;
}
else if (pid > 0)
while (--p > &FIRST_TASK)
{
if (*p && (*p)->pid == pid)
if (err = send_sig (sig, *p, 0))
retval = err;
}
else if (pid == -1)
while (--p > &FIRST_TASK)
if (err = send_sig (sig, *p, 0))
retval = err;
else
while (--p > &FIRST_TASK)
if (*p && (*p)->pgrp == -pid)
if (err = send_sig (sig, *p, 0))
retval = err;
return retval;
}
static void tell_father (int pid)
{
int i;
if (pid)
for (i = 0; i < NR_TASKS; i++)
{
if (!task[i])
continue;
if (task[i]->pid != pid)
continue;
task[i]->signal |= (1 << (SIGCHLD - 1));
return;
}
/* if we don't find any fathers, we just release ourselves */
/* This is not really OK. Must change it to make father 1 */
printk ("BAD BAD - no father found\n\r");
release (current);
}
int do_exit (long code)
{
int i;
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);
}
if (current->leader)
kill_session ();
current->state = TASK_ZOMBIE;
current->exit_code = code;
tell_father (current->father);
schedule ();
return (-1);
}
int sys_exit (int error_code)
{
return do_exit ((error_code & 0xff) << 8);
}
int sys_waitpid (int pid, unsigned long *stat_addr, int options)
{
int flag, code;
struct task_struct **p;
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;
*stat_addr = 0x7f;
return (*p)->pid;
case TASK_ZOMBIE:
current->cutime += (*p)->utime;
flag = (*p)->pid;
code = (*p)->exit_code;
release (*p);
*stat_addr = 0x7f;
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -