jake1036
My Links
C++博客
首页
新随笔
联系
聚合
管理
Blog Stats
Posts - 101
Stories - 0
Comments - 23
Trackbacks - 0
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(1)
给我留言
查看公开留言
查看私人留言
随笔分类
c++学习总结(7)
(rss)
larbin源码分析(4)
(rss)
算法相关(65)
(rss)
随笔档案
2011年9月 (4)
2011年8月 (1)
2011年7月 (5)
2011年6月 (24)
2011年5月 (34)
2011年4月 (10)
2011年3月 (4)
2010年12月 (1)
2010年11月 (7)
2010年10月 (5)
2010年9月 (5)
2010年8月 (1)
搜索
最新评论
1. re: 01背包问题总结(一)http://www.cppblog.com/Modules/CaptchaImage/JpegImage.aspx
评论内容较长,点击标题查看
--http://www.cppblog.com/Modules/CaptchaImage/JpegIm
2. re: 编程之美-2.5寻求最大的K个数[未登录]
你确定以上代码可以运行?
呵呵
--xixi
3. re: larbin源码分析(七) larbin中的2种容器与4个url队列
评论内容较长,点击标题查看
--Humton
4. re: larbin源码分析(七) larbin中的2种容器与4个url队列
评论内容较长,点击标题查看
--Humton
5. re: 动态规划法-------最大连续子序列和
@123
谁说的,明明b[7] == 25好吧
--456
阅读排行榜
1. 01背包问题总结(一)(24983)
2. 动态规划法-------最大连续子序列和(9604)
3. c++类模板学习(8025)
4. 完全背包问题 <二>(4499)
5. 编程之美1.8-----电梯调度算法(4179)
评论排行榜
1. 2011-4-16 淘宝实习生面试总结(6)
2. 动态规划法-------最大连续子序列和(3)
3. 动态规划法-----最长增序子序列(非连续)(3)
4. 面试100 34找出数组中唯一出现一次的两个数字(2)
5. larbin源码分析(七) larbin中的2种容器与4个url队列(2)
linux0.11信号处理之 exit.c
exit.c 程序解析
1 功能描述
该程序主要的作用是终止和退出的有关事宜。主要包括进程释放、会话终止和程序退出处理函数以及杀死进程,终止进程,挂起进程调用函数。还包括进程信号发送函数,以及通知父进程子进程终止的函数tell_father()。
释放进程的函数release() 主要根据制定的任务数据结构指针,在任务数组中删除指定的进程指针、释放内存页,并立刻让内核重新调度任务的运行。
kill_session() 函数通过向会话号与当前进程相同的进程发送挂断进程的信号。
sys_kill()用于向进程发送任何指定的信号。根据pid的不同参数值,该系统会向不同的进程发送任何指定的信号。
do_exit() 函数是在exit系统调用的中断处理程序中被调用。它首先会释放当前进程的内存页面。如果当前进程有子进程,就将子进程的father置为1 ,即把子进程的父进程变为进程1(init进程)。如果该子进程已经处于僵死的状态,那么向进程1发送子进程终止信号SIGCHLD 。接着关闭当前进程打开的所有文件,释放试验的中断设备。
协处理器设备,若当前进程是进程组的领头进程,则还需要终止所有相关进程。 随后把当前进程置位僵死状态,设置退出码,并向父进程发送子进程终止信号SIGCHLD。最后让内核重新调度任务运行。
2 代码示例
#include
<
errno.h
>
#include
<
signal.h
>
#include
<
sys
/
wait.h
>
#include
<
linux
/
sched.h
>
#include
<
linux
/
kernel.h
>
#include
<
linux
/
tty.h
>
#include
<
asm
/
segment.h
>
int
sys_pause(
void
) ;
//
把进程置为睡眠状态
int
sys_close(
int
fd) ;
//
关闭指定文件的系统调用
//
释放指定进程所占用的任务槽,及其任务数据结构占用的内存页面
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_page((
long
)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())
//
euid表示当前进程的权限
p
->
signal
|=
(
1
<<
(sig
-
1
)) ;
else
return
-
EPERM ;
return
0
;
}
//
终止会话session
static
void
kill_session(
void
)
{
struct
task_struct
**
p
=
NR_TASKS
+
task ;
//
*p首先指向最后一个任务
//
扫描任务指针数组,如果所有的任务的会话号等于当前进程的会话号,那么就向它发送终止信号
for
(;p
>=
&
FIRST_TASK ; p
--
)
{
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)
{
//
如果当前进程pid==0。那么就会把信号发送给与当前进程在同一组中的进程
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
==
current
->
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 ;
}
//
通知父进程--向进程pid发送信号SIGCHLD ;默认情况下子进程将停止或者终止
//
如果没有找到父进程,则自己释放。
static
void
tell_father(
int
pid)
{
int
i ;
if
(pid)
//
扫描进程数组表寻找指定进程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
;
}
//
如果没有找到父进程,则进程就自己释放。
printk(
"
BAD BAD - no father found\b\r
"
) ;
release(current) ;
}
//
程序退出处理函数。在下面的sys_exit()函数中被调用
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
)) ;
//
如果当前进程有子进程,将子进程的father置为1。
//
若该子进程已经处于僵死状态,则向进程1发送子进程终止信号SIGCHLD
//
如果该子进程已经处于僵死状态,则向进程1发送子进程终止信号
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)
(
void
)send_sig(SIGCHLD , task[
1
] ,
1
) ;
}
//
关闭当前进程打开着的全部文件
for
(i
=
0
; i
<
NR_OPEN ;i
++
)
if
(current
->
filp[i])
sys_close(i) ;
//
对当前进程的工作目录pwd,跟目录root以及执行文件的i节点进行同步操作,放回各个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
;
//
如果当前进程上次使用过协处理器,则将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 ;
tell_father(current
->
father) ;
//
通知父进程,子进程将结束
schedule() ;
//
重新调度进程运行
return
(
-
1
) ;
}
//
系统调用exit()。终止进程
int
sys_exit(
int
error_code)
{
return
do_exit((error_code
&
0xff
)
<<
8
) ;
}
//
挂起当前进程,等待pid指定的子进程退出或者收到终止该进程的信号,或者是需要一个信号句柄
int
sys_waitpid(pid_t pid , unsigned
long
*
stat_addr ,
int
options)
{
int
flag , code ;
//
flag标志作用于后面表示所选出的子进程处于就绪或者睡眠状态
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
;
//
此时选择到的进程一定是当前进程的子进程
//
如果当前的pid>0,但是不等于参数pid
//
就说明是当前进程其他的子进程
if
(pid
>
0
)
{
if
((
*
p)
->
pid
!=
pid)
{
continue
;
}
}
else
if
(
!
pid)
{
//
如果pid==0,则表示正在等待组号等于当前进程的所有进程
if
((
*
p)
->
pgrp
!=
current
->
pgrp)
continue
;
}
else
if
(pid
!=
-
1
)
{
//
如果pid<-1
if
((
*
p)
->
pgrp
!=
-
pid)
continue
;
}
//
如果前3个对pid的判断不符合标准,则表示当前进程正在等待其他任何子进程,即pid=-1的情况
//
接下来根据子进程的状态来处理
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 ;
}
posted on 2010-11-07 15:43
kahn
阅读(1084)
评论(0)
编辑
收藏
引用
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © kahn