本文长期更新!
由于要换电脑,所以更新要等几天时间!以下是基于linux0.11的代码
1.做CPU工作模式的转化
2.进行寄存器的拷贝与压栈
3.设置中断向量表
4.保存正常运行的函数返回值
5.跳转到对应的中断服务函数上运行
6.进行模式的复原及寄存器的复原
7.跳转回正常工作的函数地址继续运行
1.将所有寄存器值入栈
2.将异常吗入栈(中断号)
3.将当前函数的返回地址入栈
4.调用中断函数
5.返回地址出栈
6.寄存器值出栈
中断前后的处理 中断的执行
硬件中断的处理过程 asm.s trap.c
软件及系统调用的处理过程 system_call.s fork.c/signal.c/exit.c/sys.c
在system_call.s内有存在fork的系统调用,先call _find_empty_process,然后call _copy_process
1、在task链表中找一个进程空位存放
2、创建一个task_struct
3、设置task_struct
这里只是进行一个简单的分析,详细分析请见第五章
do_exit()
sys_waitpid()
1.父进程在运行子进程时一般都会运行wait waitpid这两个函数,用来父进程等待子进程终止
2.当父进程收到SIGCHLD信号时,父进程会终止僵死状态的子进程
3.父进程会把子进程的运行时间累加到自己的运行时间上
4.把对应子进程的进程描述结构体进行释放,置空数组空槽
每创建一个进程就对应着一个task_struct结构体
1、0号和1号进程的创建
Linux在初始化的过程中会进行0号进程的创建
注:分析0.11的main函数
内核要先切换到用户态之后再fork生成0号进程
iret是从中断返回的指令,在iret之前,之前5个push压入的数据会出栈,分别赋给ss,esp,eflags,cs,eip,
fork生成0进程之后,会进行初始化,进一步分析如下
1、0号进程打开标准输入输出错误句柄
2、创建1号进程,首先打开"/dev/rc"文件,执行shell
3、如果1号进程创建失败,会换一种方式再次创建
4、之后就是进行pause()暂停状态,系统等待运行下一步
####
众所周知每创建一个进程都会创建一个相对应的task_struct结构体,task结构体里就有代表该进程唯一的PID;
这是Sched.c函数,
就是exit.c函数的操作
1、进程,线程
创建一个进程之后,就会对应一个task_struct结构体,fork之后,会进行写实复制(Copy-On-Write),也就是说子进程和父进程的内容大部分是一致的。
问:一个进程多个线程的调度方式和一个进程一个线程时的调度方式有什么区别?
答:没有区别,内核中线程和进程都需要do_fork来实现,所以没有区别。
由PC机的BIOS(0xFFFF0是BIOS存储的总线地址)把bootsect从某个固定的地址拿到了内存中的某个固定地址(0x90000),并且进行了一系列的硬件初始化和参数设置
磁盘引导块程序,在磁盘的第一个扇区中的程序(0磁道,0磁头,1扇区)
作用:首先将后续的setup.s代码从磁盘中加载到紧接着bootsect.s的地方,在显示屏上显示loading system ,再将操作系统加载到0x10000,最后转到setup.s运行
解析BIOS/Bootloader传进来的参数,设置系统内核运行的LDT(局部描述符),IDT(中断描述符) GDT(全局描述符),设置中断控制芯片,进入保护模式运行;跳转到head.s运行
GDT(global descriptor table),全局段描述符表,这些64kb数据整齐的排列在内存中某一位置。而该位置的内存地址以及有效的个数就存放在GDTR中,GDTR是特殊的寄存器。GDT在系统内只存在一个。
LDT(local descripotr table),局部段描述符表,LDT在系统内可存在多个,每个任务最多只能拥有一个LDT,另外,每一个LDT自身作为一个段存在,它们的段描述符被放在GDT中。
IDT(interrupt descriptor table),中断描述符表,IDT记录了0~255的中断号码和中断服务函数的关系。当发生中断的时候,通过中断号码去执行中断服务函数。
GDT可以被放在内存的任何位置,那么当程序员通过段寄存器来引用一个段描述符时,CPU必须知道GDT的入口,也就是基地址放在哪里,所以Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此寄存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。
IA-32为LDT的入口地址也提供了一个寄存器LDTR,因为在任何时刻只能有一个任务在运行,所以LDT寄存器全局也只需要有一个。如果一个任务拥有自身的LDT,那么当它需要引用自身的LDT时,它需要通过LLDT指令将其LDT的段描述符装入此寄存器。LLDT指令与LGDT指令不同的时,LGDT指令的操作数是一个32-bit的内存地址,这个内存地址处存放的是一个32-bit GDT的入口地址,以及16-bit的GDT Limit。而LLDT指令的操作数是一个16-bit的选择子,这个选择子主要内容是:被装入的LDT的段描述符在GDT中的索引值。
加载内核运行时的各数据段寄存器,重新设置中断描述符表,开启内核正常运行时的协处理器等资源;设置内存管理的分页机制,跳转到main.c运行
内核的信号量是很重要的,关于信号的定义在/include/signal.h文件内,比如运行一个elf文件可能会出现段错误(SIGSEGV),玩pwn的同学应该很熟悉。在system_call.s中存在call do_signal,那么do_signal在/kernel/signal.c内定义。
硬件来源:信号由硬件驱动产生
软件来源:系统提供了些API,例如kill命令
当进程收到信号时,会有三种场景;
忽略:忽略信号
执行:执行每个信号所对应的操作
执行自定操作:用户自定义的操作
1.在系统中什么是信号,都有什么信号?
2.在系统接收到信号后,是如何进行处理的?
3.信号作用
顾名思义就是文件所组成的一个系统,linux下所谓“一切皆文件”,所以文件系统在内核中占了很大比重。
Linux启动过程:
1.PCB上电后先由uboot初始化板子,然后将linux内核迁移到内存中运行;
2.由linux内核进行初始化操作,挂载第一个应用程序即根文件系统(linuxrc);
3.根文件系统提供磁盘管理服务(glibc,设备节点,配置文件,应用程序 shell命令)。
文件系统主要包括四个部分:高速缓冲区管理,文件底层操作,文件数据访问,文件高层访问控制。
程序包括对i节点位图和逻辑块位图进行释放和占用处理函数。操作i节点位图的函数是free_inode()和new_inode(),操作逻辑块位图的函数是free_block()和new_block()
程序包括对数据文件长度截断为0的函数truncate(),他将i节点指定的设备上文件长度截为0,并释放文件数据占用的设备逻辑块。
程序包括分配i节点函数iget()和放回对内存i节点存取函数iput()以及根据i节点信息取文件数据块在设备上对应的逻辑块号函数bmap()。
程序主要包括函数namei(),该函数使用iget(),iput(),bmap()将给定的文件路径名映射到其i节点。
程序专门用于处理文件系统超级块,包括函数get_super(),put_super()和free_super()和free_super()等,还包括几个文件系统加载/卸载处理函数和系统调用,如sys_mount()等
程序中的函数block_read()和block_write()是用于读写块设备特殊文件的数据,所使用的参数指定要访问的设备号,起始地址和长度
程序中的file_read()和file_write()函数是用于访问一般的文件,所使用的参数指定文件对应的i节点和文件结构。
文件中实现了管道读写函数read_pipe()和write_pipe(),另外还实现了创建无名管道的系统调用pipe(),
系统调用使用read()和write()会调用char_dev.c中的rw_char()函数来操作。字符设备包括控制台终端,串口终端和内存字符设备。
文件用于实现与文件操作相关的系统调用,主要有文件的创建,打开和关闭,文件宿主和属性修改,文件访问权限和操作时间的修改等。
程序实现对二进制可执行文件和shell脚本文件的加载与执行,其中主要是的do_execve(),他是系统中断调用(int 0x80)的功能号__NR_execve()调用的C处理函数,更是exec()函数簇的主要实现函数。
实现了文件控制操作的系统调用fcntl()和两个文件句柄(描述符)复制系统调用dup()和dup2(),dup2()指定了新句柄的数值,dup()则返回当前最小值的未用句柄。句柄复制操作主要用在文件的标准输入/输出重定向和管道操作方面。
文件实现了输入/输出控制系统调用ioctl(),主要调用tty_ioctl()函数,对终端的I/O进行控制。
文件用于实现取得文件状态信息的系统调用,stat()和fstat()。stat()是利用文件名取信息,而fstat()是利用文件句柄取信息。
高速缓冲区位于内核代码与主内存区之间,在块设备与内核其他程序之间起着一个桥梁作用,除了块设备驱动程序以外,内核程序如果需要访问块设备中的数据,就需要通过高速缓冲区来进行操作。
.align
2
_sys_fork:
call _find_empty_process
testl
%
eax,
%
eax
js
1f
push
%
gs
pushl
%
esi
pushl
%
edi
pushl
%
ebp
pushl
%
eax
call _copy_process
addl $
20
,
%
esp
1
: ret
.align
2
_sys_fork:
call _find_empty_process
testl
%
eax,
%
eax
js
1f
push
%
gs
pushl
%
esi
pushl
%
edi
pushl
%
ebp
pushl
%
eax
call _copy_process
addl $
20
,
%
esp
1
: ret
extern void write_verify(unsigned
long
address);
long
last_pid
=
0
;
void verify_area(void
*
addr,
int
size)
{
unsigned
long
start;
start
=
(unsigned
long
) addr;
size
+
=
start &
0xfff
;
start &
=
0xfffff000
;
start
+
=
get_base(current
-
>ldt[
2
]);
while
(size>
0
) {
size
-
=
4096
;
write_verify(start);
start
+
=
4096
;
}
}
int
copy_mem(
int
nr,struct task_struct
*
p)
{
unsigned
long
old_data_base,new_data_base,data_limit;
unsigned
long
old_code_base,new_code_base,code_limit;
code_limit
=
get_limit(
0x0f
);
data_limit
=
get_limit(
0x17
);
old_code_base
=
get_base(current
-
>ldt[
1
]);
old_data_base
=
get_base(current
-
>ldt[
2
]);
if
(old_data_base !
=
old_code_base)
panic(
"We don't support separate I&D"
);
if
(data_limit < code_limit)
panic(
"Bad data_limit"
);
new_data_base
=
new_code_base
=
nr
*
0x4000000
;
p
-
>start_code
=
new_code_base;
set_base(p
-
>ldt[
1
],new_code_base);
set_base(p
-
>ldt[
2
],new_data_base);
if
(copy_page_tables(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit);
return
-
ENOMEM;
}
return
0
;
}
/
*
*
Ok, this
is
the main fork
-
routine. It copies the system process
*
information (task[nr])
and
sets up the necessary registers. It
*
also copies the data segment
in
it's entirety.
*
/
int
copy_process(
int
nr,
long
ebp,
long
edi,
long
esi,
long
gs,
long
none,
long
ebx,
long
ecx,
long
edx,
long
fs,
long
es,
long
ds,
long
eip,
long
cs,
long
eflags,
long
esp,
long
ss)
{
struct task_struct
*
p;
/
/
创建子进程的task_struct结构体
int
i;
struct
file
*
f;
p
=
(struct task_struct
*
) get_free_page();
if
(!p)
return
-
EAGAIN;
task[nr]
=
p;
/
/
将子进程存到task链表中
*
p
=
*
current;
/
*
NOTE! this doesn't copy the supervisor stack
*
/
/
/
下面开始设置结构体内容
p
-
>state
=
TASK_UNINTERRUPTIBLE;
p
-
>pid
=
last_pid;
p
-
>father
=
current
-
>pid;
p
-
>counter
=
p
-
>priority;
p
-
>signal
=
0
;
p
-
>alarm
=
0
;
p
-
>leader
=
0
;
/
*
process leadership doesn't inherit
*
/
p
-
>utime
=
p
-
>stime
=
0
;
p
-
>cutime
=
p
-
>cstime
=
0
;
p
-
>start_time
=
jiffies;
p
-
>tss.back_link
=
0
;
p
-
>tss.esp0
=
PAGE_SIZE
+
(
long
) p;
p
-
>tss.ss0
=
0x10
;
p
-
>tss.eip
=
eip;
p
-
>tss.eflags
=
eflags;
p
-
>tss.eax
=
0
;
p
-
>tss.ecx
=
ecx;
p
-
>tss.edx
=
edx;
p
-
>tss.ebx
=
ebx;
p
-
>tss.esp
=
esp;
p
-
>tss.ebp
=
ebp;
p
-
>tss.esi
=
esi;
p
-
>tss.edi
=
edi;
p
-
>tss.es
=
es &
0xffff
;
p
-
>tss.cs
=
cs &
0xffff
;
p
-
>tss.ss
=
ss &
0xffff
;
p
-
>tss.ds
=
ds &
0xffff
;
p
-
>tss.fs
=
fs &
0xffff
;
p
-
>tss.gs
=
gs &
0xffff
;
p
-
>tss.ldt
=
_LDT(nr);
p
-
>tss.trace_bitmap
=
0x80000000
;
if
(last_task_used_math
=
=
current)
__asm__(
"clts ; fnsave %0"
::
"m"
(p
-
>tss.i387));
/
/
如果父进程用了协处理器,需要在tss段进行设置
if
(copy_mem(nr,p)) {
/
/
内存拷贝
task[nr]
=
NULL;
free_page((
long
) p);
return
-
EAGAIN;
}
for
(i
=
0
; i<NR_OPEN;i
+
+
)
if
(f
=
p
-
>filp[i])
f
-
>f_count
+
+
;
if
(current
-
>pwd)
current
-
>pwd
-
>i_count
+
+
;
if
(current
-
>root)
current
-
>root
-
>i_count
+
+
;
if
(current
-
>executable)
current
-
>executable
-
>i_count
+
+
;
set_tss_desc(gdt
+
(nr<<
1
)
+
FIRST_TSS_ENTRY,&(p
-
>tss));
set_ldt_desc(gdt
+
(nr<<
1
)
+
FIRST_LDT_ENTRY,&(p
-
>ldt));
p
-
>state
=
TASK_RUNNING;
/
*
do this last, just
in
case
*
/
return
last_pid;
}
int
find_empty_process(void)
{
int
i;
repeat:
if
((
+
+
last_pid)<
0
) last_pid
=
1
;
for
(i
=
0
; i<NR_TASKS ; i
+
+
)
if
(task[i] && task[i]
-
>pid
=
=
last_pid) goto repeat;
for
(i
=
1
; i<NR_TASKS ; i
+
+
)
if
(!task[i])
return
i;
return
-
EAGAIN;
}
extern void write_verify(unsigned
long
address);
long
last_pid
=
0
;
void verify_area(void
*
addr,
int
size)
{
unsigned
long
start;
start
=
(unsigned
long
) addr;
size
+
=
start &
0xfff
;
start &
=
0xfffff000
;
start
+
=
get_base(current
-
>ldt[
2
]);
while
(size>
0
) {
size
-
=
4096
;
write_verify(start);
start
+
=
4096
;
}
}
int
copy_mem(
int
nr,struct task_struct
*
p)
{
unsigned
long
old_data_base,new_data_base,data_limit;
unsigned
long
old_code_base,new_code_base,code_limit;
code_limit
=
get_limit(
0x0f
);
data_limit
=
get_limit(
0x17
);
old_code_base
=
get_base(current
-
>ldt[
1
]);
old_data_base
=
get_base(current
-
>ldt[
2
]);
if
(old_data_base !
=
old_code_base)
panic(
"We don't support separate I&D"
);
if
(data_limit < code_limit)
panic(
"Bad data_limit"
);
new_data_base
=
new_code_base
=
nr
*
0x4000000
;
p
-
>start_code
=
new_code_base;
set_base(p
-
>ldt[
1
],new_code_base);
set_base(p
-
>ldt[
2
],new_data_base);
if
(copy_page_tables(old_data_base,new_data_base,data_limit)) {
free_page_tables(new_data_base,data_limit);
return
-
ENOMEM;
}
return
0
;
}
/
*
*
Ok, this
is
the main fork
-
routine. It copies the system process
*
information (task[nr])
and
sets up the necessary registers. It
*
also copies the data segment
in
it's entirety.
*
/
int
copy_process(
int
nr,
long
ebp,
long
edi,
long
esi,
long
gs,
long
none,
long
ebx,
long
ecx,
long
edx,
long
fs,
long
es,
long
ds,
long
eip,
long
cs,
long
eflags,
long
esp,
long
ss)
{
struct task_struct
*
p;
/
/
创建子进程的task_struct结构体
int
i;
struct
file
*
f;
p
=
(struct task_struct
*
) get_free_page();
if
(!p)
return
-
EAGAIN;
task[nr]
=
p;
/
/
将子进程存到task链表中
*
p
=
*
current;
/
*
NOTE! this doesn't copy the supervisor stack
*
/
/
/
下面开始设置结构体内容
p
-
>state
=
TASK_UNINTERRUPTIBLE;
p
-
>pid
=
last_pid;
p
-
>father
=
current
-
>pid;
p
-
>counter
=
p
-
>priority;
p
-
>signal
=
0
;
p
-
>alarm
=
0
;
p
-
>leader
=
0
;
/
*
process leadership doesn't inherit
*
/
p
-
>utime
=
p
-
>stime
=
0
;
p
-
>cutime
=
p
-
>cstime
=
0
;
p
-
>start_time
=
jiffies;
p
-
>tss.back_link
=
0
;
p
-
>tss.esp0
=
PAGE_SIZE
+
(
long
) p;
p
-
>tss.ss0
=
0x10
;
p
-
>tss.eip
=
eip;
p
-
>tss.eflags
=
eflags;
p
-
>tss.eax
=
0
;
p
-
>tss.ecx
=
ecx;
p
-
>tss.edx
=
edx;
p
-
>tss.ebx
=
ebx;
p
-
>tss.esp
=
esp;
p
-
>tss.ebp
=
ebp;
p
-
>tss.esi
=
esi;
p
-
>tss.edi
=
edi;
p
-
>tss.es
=
es &
0xffff
;
p
-
>tss.cs
=
cs &
0xffff
;
p
-
>tss.ss
=
ss &
0xffff
;
p
-
>tss.ds
=
ds &
0xffff
;
p
-
>tss.fs
=
fs &
0xffff
;
p
-
>tss.gs
=
gs &
0xffff
;
p
-
>tss.ldt
=
_LDT(nr);
p
-
>tss.trace_bitmap
=
0x80000000
;
if
(last_task_used_math
=
=
current)
__asm__(
"clts ; fnsave %0"
::
"m"
(p
-
>tss.i387));
/
/
如果父进程用了协处理器,需要在tss段进行设置
if
(copy_mem(nr,p)) {
/
/
内存拷贝
task[nr]
=
NULL;
free_page((
long
) p);
return
-
EAGAIN;
}
for
(i
=
0
; i<NR_OPEN;i
+
+
)
if
(f
=
p
-
>filp[i])
f
-
>f_count
+
+
;
if
(current
-
>pwd)
current
-
>pwd
-
>i_count
+
+
;
if
(current
-
>root)
current
-
>root
-
>i_count
+
+
;
if
(current
-
>executable)
current
-
>executable
-
>i_count
+
+
;
set_tss_desc(gdt
+
(nr<<
1
)
+
FIRST_TSS_ENTRY,&(p
-
>tss));
set_ldt_desc(gdt
+
(nr<<
1
)
+
FIRST_LDT_ENTRY,&(p
-
>ldt));
p
-
>state
=
TASK_RUNNING;
/
*
do this last, just
in
case
*
/
return
last_pid;
}
int
find_empty_process(void)
{
int
i;
repeat:
if
((
+
+
last_pid)<
0
) last_pid
=
1
;
for
(i
=
0
; i<NR_TASKS ; i
+
+
)
if
(task[i] && task[i]
-
>pid
=
=
last_pid) goto repeat;
for
(i
=
1
; i<NR_TASKS ; i
+
+
)
if
(!task[i])
return
i;
return
-
EAGAIN;
}
volatile void do_exit(
int
error_code);
int
sys_sgetmask()
{
return
current
-
>blocked;
}
int
sys_ssetmask(
int
newmask)
{
int
old
=
current
-
>blocked;
current
-
>blocked
=
newmask & ~(
1
<<(SIGKILL
-
1
));
return
old;
}
static inline void save_old(char
*
from
,char
*
to)
{
int
i;
verify_area(to, sizeof(struct sigaction));
for
(i
=
0
; i< sizeof(struct sigaction) ; i
+
+
) {
put_fs_byte(
*
from
,to);
from
+
+
;
to
+
+
;
}
}
static inline void get_new(char
*
from
,char
*
to)
{
int
i;
for
(i
=
0
; i< sizeof(struct sigaction) ; i
+
+
)
*
(to
+
+
)
=
get_fs_byte(
from
+
+
);
}
int
sys_signal(
int
signum,
long
handler,
long
restorer)
{
struct sigaction tmp;
if
(signum<
1
|| signum>
32
|| signum
=
=
SIGKILL)
/
/
判断信号值是否合法
return
-
1
;
tmp.sa_handler
=
(void (
*
)(
int
)) handler;
tmp.sa_mask
=
0
;
tmp.sa_flags
=
SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer
=
(void (
*
)(void)) restorer;
/
/
设置sigaction结构体
handler
=
(
long
) current
-
>sigaction[signum
-
1
].sa_handler;
current
-
>sigaction[signum
-
1
]
=
tmp;
/
/
将当前进程对应的信号结构体改为新分配的结构体
return
handler;
/
/
返回处理函数
}
int
sys_sigaction(
int
signum, const struct sigaction
*
action,
struct sigaction
*
oldaction)
{
struct sigaction tmp;
if
(signum<
1
|| signum>
32
|| signum
=
=
SIGKILL)
return
-
1
;
tmp
=
current
-
>sigaction[signum
-
1
];
get_new((char
*
) action,
(char
*
) (signum
-
1
+
current
-
>sigaction));
if
(oldaction)
save_old((char
*
) &tmp,(char
*
) oldaction);
if
(current
-
>sigaction[signum
-
1
].sa_flags & SA_NOMASK)
current
-
>sigaction[signum
-
1
].sa_mask
=
0
;
else
current
-
>sigaction[signum
-
1
].sa_mask |
=
(
1
<<(signum
-
1
));
return
0
;
}
void do_signal(
long
signr,
long
eax,
long
ebx,
long
ecx,
long
edx,
long
fs,
long
es,
long
ds,
long
eip,
long
cs,
long
eflags,
unsigned
long
*
esp,
long
ss)
{
unsigned
long
sa_handler;
long
old_eip
=
eip;
struct sigaction
*
sa
=
current
-
>sigaction
+
signr
-
1
;
int
longs;
unsigned
long
*
tmp_esp;
sa_handler
=
(unsigned
long
) sa
-
>sa_handler;
if
(sa_handler
=
=
1
)
return
;
if
(!sa_handler) {
if
(signr
=
=
SIGCHLD)
return
;
else
do_exit(
1
<<(signr
-
1
));
}
if
(sa
-
>sa_flags & SA_ONESHOT)
sa
-
>sa_handler
=
NULL;
*
(&eip)
=
sa_handler;
longs
=
(sa
-
>sa_flags & SA_NOMASK)?
7
:
8
;
*
(&esp)
-
=
longs;
verify_area(esp,longs
*
4
);
tmp_esp
=
esp;
put_fs_long((
long
) sa
-
>sa_restorer,tmp_esp
+
+
);
put_fs_long(signr,tmp_esp
+
+
);
if
(!(sa
-
>sa_flags & SA_NOMASK))
put_fs_long(current
-
>blocked,tmp_esp
+
+
);
put_fs_long(eax,tmp_esp
+
+
);
put_fs_long(ecx,tmp_esp
+
+
);
put_fs_long(edx,tmp_esp
+
+
);
put_fs_long(eflags,tmp_esp
+
+
);
put_fs_long(old_eip,tmp_esp
+
+
);
current
-
>blocked |
=
sa
-
>sa_mask;
}
volatile void do_exit(
int
error_code);
int
sys_sgetmask()
{
return
current
-
>blocked;
}
int
sys_ssetmask(
int
newmask)
{
int
old
=
current
-
>blocked;
current
-
>blocked
=
newmask & ~(
1
<<(SIGKILL
-
1
));
return
old;
}
static inline void save_old(char
*
from
,char
*
to)
{
int
i;
verify_area(to, sizeof(struct sigaction));
for
(i
=
0
; i< sizeof(struct sigaction) ; i
+
+
) {
put_fs_byte(
*
from
,to);
from
+
+
;
to
+
+
;
}
}
static inline void get_new(char
*
from
,char
*
to)
{
int
i;
for
(i
=
0
; i< sizeof(struct sigaction) ; i
+
+
)
*
(to
+
+
)
=
get_fs_byte(
from
+
+
);
}
int
sys_signal(
int
signum,
long
handler,
long
restorer)
{
struct sigaction tmp;
if
(signum<
1
|| signum>
32
|| signum
=
=
SIGKILL)
/
/
判断信号值是否合法
return
-
1
;
tmp.sa_handler
=
(void (
*
)(
int
)) handler;
tmp.sa_mask
=
0
;
tmp.sa_flags
=
SA_ONESHOT | SA_NOMASK;
tmp.sa_restorer
=
(void (
*
)(void)) restorer;
/
/
设置sigaction结构体
handler
=
(
long
) current
-
>sigaction[signum
-
1
].sa_handler;
current
-
>sigaction[signum
-
1
]
=
tmp;
/
/
将当前进程对应的信号结构体改为新分配的结构体
return
handler;
/
/
返回处理函数
}
int
sys_sigaction(
int
signum, const struct sigaction
*
action,
struct sigaction
*
oldaction)
{
struct sigaction tmp;
if
(signum<
1
|| signum>
32
|| signum
=
=
SIGKILL)
return
-
1
;
tmp
=
current
-
>sigaction[signum
-
1
];
get_new((char
*
) action,
(char
*
) (signum
-
1
+
current
-
>sigaction));
if
(oldaction)
save_old((char
*
) &tmp,(char
*
) oldaction);
if
(current
-
>sigaction[signum
-
1
].sa_flags & SA_NOMASK)
current
-
>sigaction[signum
-
1
].sa_mask
=
0
;
else
current
-
>sigaction[signum
-
1
].sa_mask |
=
(
1
<<(signum
-
1
));
return
0
;
}
void do_signal(
long
signr,
long
eax,
long
ebx,
long
ecx,
long
edx,
long
fs,
long
es,
long
ds,
long
eip,
long
cs,
long
eflags,
unsigned
long
*
esp,
long
ss)
{
unsigned
long
sa_handler;
long
old_eip
=
eip;
struct sigaction
*
sa
=
current
-
>sigaction
+
signr
-
1
;
int
longs;
unsigned
long
*
tmp_esp;
sa_handler
=
(unsigned
long
) sa
-
>sa_handler;
if
(sa_handler
=
=
1
)
return
;
if
(!sa_handler) {
if
(signr
=
=
SIGCHLD)
return
;
else
do_exit(
1
<<(signr
-
1
));
}
if
(sa
-
>sa_flags & SA_ONESHOT)
sa
-
>sa_handler
=
NULL;
*
(&eip)
=
sa_handler;
longs
=
(sa
-
>sa_flags & SA_NOMASK)?
7
:
8
;
*
(&esp)
-
=
longs;
verify_area(esp,longs
*
4
);
tmp_esp
=
esp;
put_fs_long((
long
) sa
-
>sa_restorer,tmp_esp
+
+
);
put_fs_long(signr,tmp_esp
+
+
);
if
(!(sa
-
>sa_flags & SA_NOMASK))
put_fs_long(current
-
>blocked,tmp_esp
+
+
);
put_fs_long(eax,tmp_esp
+
+
);
put_fs_long(ecx,tmp_esp
+
+
);
put_fs_long(edx,tmp_esp
+
+
);
put_fs_long(eflags,tmp_esp
+
+
);
put_fs_long(old_eip,tmp_esp
+
+
);
current
-
>blocked |
=
sa
-
>sa_mask;
}
/
/
Line
12
/
/
Line
37
/
/
Line
45
typedef unsigned
int
sigset_t;
struct sigaction {
void (
*
sa_handler)(
int
);
/
/
信号处理程序指针
sigset_t sa_mask;
/
/
指出当前信号处理程序执行期间需要被屏蔽的信号
int
sa_flags;
/
/
从
37
行的三个定义中选出
void (
*
sa_restorer)(void);
/
/
恢复函数指针,由 libc 提供
};
/
/
Line
12
/
/
Line
37
/
/
Line
45
typedef unsigned
int
sigset_t;
struct sigaction {
void (
*
sa_handler)(
int
);
/
/
信号处理程序指针
sigset_t sa_mask;
/
/
指出当前信号处理程序执行期间需要被屏蔽的信号
int
sa_flags;
/
/
从
37
行的三个定义中选出
void (
*
sa_restorer)(void);
/
/
恢复函数指针,由 libc 提供
};
int
sys_pause(void);
int
sys_close(
int
fd);
void release(struct task_struct
*
p)
/
/
释放进程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())
p
-
>signal |
=
(
1
<<(sig
-
1
));
/
/
给p进程发送信号
else
return
-
EPERM;
return
0
;
}
static void kill_session(void)
/
/
关闭对话函数
{
struct task_struct
*
*
p
=
NR_TASKS
+
task;
/
/
获得task数组最后一个任务
while
(
-
-
p > &FIRST_TASK) {
/
/
从最后一个向前遍历
if
(
*
p && (
*
p)
-
>session
=
=
current
-
>session)
/
/
如果遍历到当前的任务
(
*
p)
-
>signal |
=
1
<<(SIGHUP
-
1
);
/
/
则将SIGHUP挂断信号发送给当前任务
}
}
/
*
*
XXX need to check permissions needed to send signals to process
*
groups, etc. etc. kill() permissions semantics are tricky!
*
/
int
sys_kill(
int
pid,
int
sig)
/
/
linux命令kill不是杀死的意思,是向某进程发送任何信号
{
struct task_struct
*
*
p
=
NR_TASKS
+
task;
/
/
指向最后
int
err, retval
=
0
;
/
/
注: 每个进程组都有一个组长进程,组长进程的进程号等于进程组
ID
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) {
/
/
如果pid大于
0
if
(
*
p && (
*
p)
-
>pid
=
=
pid)
/
/
仅向pid进程发送信号
if
(err
=
send_sig(sig,
*
p,
0
))
retval
=
err;
}
else
if
(pid
=
=
-
1
)
while
(
-
-
p > &FIRST_TASK)
/
/
如果pid
=
-
1
if
(err
=
send_sig(sig,
*
p,
0
))
/
/
向除
0
号进程外的进程发送信号
retval
=
err;
else
while
(
-
-
p > &FIRST_TASK)
/
/
如果pid<
-
1
if
(
*
p && (
*
p)
-
>pgrp
=
=
-
pid)
/
/
向进程组号为
-
pid的进程组发送信号
if
(err
=
send_sig(sig,
*
p,
0
))
retval
=
err;
return
retval;
}
static void tell_father(
int
pid)
/
/
传入参数为父进程的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
));
/
/
SIGCHLD
=
17
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;
/
/
/
/
/
/
free_page_tables(get_base(current
-
>ldt[
1
]),get_limit(
0x0f
));
/
/
释放当前进程的CODE段所占用的内存页
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
;
/
/
就让
1
号进程作为某个进程的父进程(因为current这个进程将会exit)
if
(task[i]
-
>state
=
=
TASK_ZOMBIE)
/
/
若某进程是僵死状态
/
*
assumption task[
1
]
is
always init
*
/
(void) send_sig(SIGCHLD, task[
1
],
1
);
/
/
给
1
号进程发送信号
}
for
(i
=
0
; i<NR_OPEN ; i
+
+
)
if
(current
-
>filp[i])
/
/
关闭当前进程打开的所有文件
sys_close(i);
iput(current
-
>pwd);
/
/
把当前进程的路径放回i节点并置空
current
-
>pwd
=
NULL;
iput(current
-
>root);
current
-
>root
=
NULL;
iput(current
-
>executable);
current
-
>executable
=
NULL;
if
(current
-
>leader && current
-
>tty >
=
0
)
/
/
若当前进程是进程组的头头,并且拥有tty终端
tty_table[current
-
>tty].pgrp
=
0
;
/
/
释放该终端
if
(last_task_used_math
=
=
current)
last_task_used_math
=
NULL;
if
(current
-
>leader)
kill_session();
/
/
关闭session
current
-
>state
=
TASK_ZOMBIE;
/
/
设置成僵死状态
current
-
>exit_code
=
code;
tell_father(current
-
>father);
/
/
向当前进程的父进程发送 SIGCHLD 信号
schedule();
return
(
-
1
);
/
*
just to suppress warnings
*
/
}
int
sys_exit(
int
error_code)
{
return
do_exit((error_code&
0xff
)<<
8
);
}
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
) {
/
/
若pid>
0
if
((
*
p)
-
>pid !
=
pid)
/
/
若该项的pid不是waitpid传进来的pid参数,则跳过
continue
;
}
else
if
(!pid) {
/
/
若pid
=
0
,
if
((
*
p)
-
>pgrp !
=
current
-
>pgrp)
/
/
若当前项不在当前进程组,则跳过
continue
;
}
else
if
(pid !
=
-
1
) {
/
/
若pid<
-
1
if
((
*
p)
-
>pgrp !
=
-
pid)
/
/
若当前项不在
-
pid的进程组,则跳过
continue
;
}
switch ((
*
p)
-
>state) {
/
/
若pid
=
-
1
,则直接来到switch;判断所选进程p的状态
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:
/
/
p是睡眠或运行状态,设置flag为
1
flag
=
1
;
continue
;
}
}
if
(flag) {
if
(options & WNOHANG)
/
/
WNOHANG 表示若没有子进程处于退出或终止态就返回
return
0
;
current
-
>state
=
TASK_INTERRUPTIBLE;
/
/
否则将当前进程的状态置为可中断睡眠态
schedule();
if
(!(current
-
>signal &
=
~(
1
<<(SIGCHLD
-
1
))))
goto repeat;
else
return
-
EINTR;
}
return
-
ECHILD;
}
int
sys_pause(void);
int
sys_close(
int
fd);
void release(struct task_struct
*
p)
/
/
释放进程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())
p
-
>signal |
=
(
1
<<(sig
-
1
));
/
/
给p进程发送信号
else
return
-
EPERM;
return
0
;
}
static void kill_session(void)
/
/
关闭对话函数
{
struct task_struct
*
*
p
=
NR_TASKS
+
task;
/
/
获得task数组最后一个任务
while
(
-
-
p > &FIRST_TASK) {
/
/
从最后一个向前遍历
if
(
*
p && (
*
p)
-
>session
=
=
current
-
>session)
/
/
如果遍历到当前的任务
(
*
p)
-
>signal |
=
1
<<(SIGHUP
-
1
);
/
/
则将SIGHUP挂断信号发送给当前任务
}
}
/
*
*
XXX need to check permissions needed to send signals to process
*
groups, etc. etc. kill() permissions semantics are tricky!
*
/
int
sys_kill(
int
pid,
int
sig)
/
/
linux命令kill不是杀死的意思,是向某进程发送任何信号
{
struct task_struct
*
*
p
=
NR_TASKS
+
task;
/
/
指向最后
int
err, retval
=
0
;
/
/
注: 每个进程组都有一个组长进程,组长进程的进程号等于进程组
ID
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) {
/
/
如果pid大于
0
if
(
*
p && (
*
p)
-
>pid
=
=
pid)
/
/
仅向pid进程发送信号
if
(err
=
send_sig(sig,
*
p,
0
))
retval
=
err;
}
else
if
(pid
=
=
-
1
)
while
(
-
-
p > &FIRST_TASK)
/
/
如果pid
=
-
1
if
(err
=
send_sig(sig,
*
p,
0
))
/
/
向除
0
号进程外的进程发送信号
retval
=
err;
else
while
(
-
-
p > &FIRST_TASK)
/
/
如果pid<
-
1
if
(
*
p && (
*
p)
-
>pgrp
=
=
-
pid)
/
/
向进程组号为
-
pid的进程组发送信号
if
(err
=
send_sig(sig,
*
p,
0
))
retval
=
err;
return
retval;
}
static void tell_father(
int
pid)
/
/
传入参数为父进程的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
));
/
/
SIGCHLD
=
17
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;
/
/
/
/
/
/
free_page_tables(get_base(current
-
>ldt[
1
]),get_limit(
0x0f
));
/
/
释放当前进程的CODE段所占用的内存页
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
;
/
/
就让
1
号进程作为某个进程的父进程(因为current这个进程将会exit)
if
(task[i]
-
>state
=
=
TASK_ZOMBIE)
/
/
若某进程是僵死状态
/
*
assumption task[
1
]
is
always init
*
/
(void) send_sig(SIGCHLD, task[
1
],
1
);
/
/
给
1
号进程发送信号
}
for
(i
=
0
; i<NR_OPEN ; i
+
+
)
if
(current
-
>filp[i])
/
/
关闭当前进程打开的所有文件
sys_close(i);
iput(current
-
>pwd);
/
/
把当前进程的路径放回i节点并置空
current
-
>pwd
=
NULL;
iput(current
-
>root);
current
-
>root
=
NULL;
iput(current
-
>executable);
current
-
>executable
=
NULL;
if
(current
-
>leader && current
-
>tty >
=
0
)
/
/
若当前进程是进程组的头头,并且拥有tty终端
tty_table[current
-
>tty].pgrp
=
0
;
/
/
释放该终端
if
(last_task_used_math
=
=
current)
last_task_used_math
=
NULL;
if
(current
-
>leader)
kill_session();
/
/
关闭session
current
-
>state
=
TASK_ZOMBIE;
/
/
设置成僵死状态
current
-
>exit_code
=
code;
tell_father(current
-
>father);
/
/
向当前进程的父进程发送 SIGCHLD 信号
schedule();
return
(
-
1
);
/
*
just to suppress warnings
*
/
}
int
sys_exit(
int
error_code)
{
return
do_exit((error_code&
0xff
)<<
8
);
}
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
) {
/
/
若pid>
0
if
((
*
p)
-
>pid !
=
pid)
/
/
若该项的pid不是waitpid传进来的pid参数,则跳过
continue
;
}
else
if
(!pid) {
/
/
若pid
=
0
,
if
((
*
p)
-
>pgrp !
=
current
-
>pgrp)
/
/
若当前项不在当前进程组,则跳过
continue
;
}
else
if
(pid !
=
-
1
) {
/
/
若pid<
-
1
if
((
*
p)
-
>pgrp !
=
-
pid)
/
/
若当前项不在
-
pid的进程组,则跳过
continue
;
}
switch ((
*
p)
-
>state) {
/
/
若pid
=
-
1
,则直接来到switch;判断所选进程p的状态
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:
/
/
p是睡眠或运行状态,设置flag为
1
flag
=
1
;
continue
;
}
}
if
(flag) {
if
(options & WNOHANG)
/
/
WNOHANG 表示若没有子进程处于退出或终止态就返回
return
0
;
current
-
>state
=
TASK_INTERRUPTIBLE;
/
/
否则将当前进程的状态置为可中断睡眠态
schedule();
if
(!(current
-
>signal &
=
~(
1
<<(SIGCHLD
-
1
))))
goto repeat;
else
return
-
EINTR;
}
return
-
ECHILD;
}
struct task_struct {
/
*
these are hardcoded
-
don't touch
*
/
long
state;
/
*
-
1
unrunnable,
0
runnable, >
0
stopped
*
/
long
counter;
long
priority;
long
signal;
struct sigaction sigaction[
32
];
long
blocked;
/
*
bitmap of masked signals
*
/
/
*
various fields
*
/
int
exit_code;
unsigned
long
start_code,end_code,end_data,brk,start_stack;
long
pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long
alarm;
long
utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/
*
file
system info
*
/
int
tty;
/
*
-
1
if
no tty, so it must be signed
*
/
unsigned short umask;
struct m_inode
*
pwd;
struct m_inode
*
root;
struct m_inode
*
executable;
unsigned
long
close_on_exec;
struct
file
*
filp[NR_OPEN];
/
*
ldt
for
this task
0
-
zero
1
-
cs
2
-
ds&ss
*
/
struct desc_struct ldt[
3
];
/
*
tss
for
this task
*
/
struct tss_struct tss;
/
/
cpu运行一个进程后各个寄存器都保存在tss内
};
struct task_struct {
/
*
these are hardcoded
-
don't touch
*
/
long
state;
/
*
-
1
unrunnable,
0
runnable, >
0
stopped
*
/
long
counter;
long
priority;
long
signal;
struct sigaction sigaction[
32
];
long
blocked;
/
*
bitmap of masked signals
*
/
/
*
various fields
*
/
int
exit_code;
unsigned
long
start_code,end_code,end_data,brk,start_stack;
long
pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long
alarm;
long
utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/
*
file
system info
*
/
int
tty;
/
*
-
1
if
no tty, so it must be signed
*
/
unsigned short umask;
struct m_inode
*
pwd;
struct m_inode
*
root;
struct m_inode
*
executable;
unsigned
long
close_on_exec;
struct
file
*
filp[NR_OPEN];
/
*
ldt
for
this task
0
-
zero
1
-
cs
2
-
ds&ss
*
/
struct desc_struct ldt[
3
];
/
*
tss
for
this task
*
/
struct tss_struct tss;
/
/
cpu运行一个进程后各个寄存器都保存在tss内
};
void main(void)
/
*
This really IS void, no error here.
*
/
{
/
*
The startup routine assumes (well, ...) this
*
/
/
*
*
Interrupts are still disabled. Do necessary setups, then
*
enable them
*
/
ROOT_DEV
=
ORIG_ROOT_DEV;
drive_info
=
DRIVE_INFO;
memory_end
=
(
1
<<
20
)
+
(EXT_MEM_K<<
10
);
memory_end &
=
0xfffff000
;
if
(memory_end >
16
*
1024
*
1024
)
memory_end
=
16
*
1024
*
1024
;
if
(memory_end >
12
*
1024
*
1024
)
buffer_memory_end
=
4
*
1024
*
1024
;
else
if
(memory_end >
6
*
1024
*
1024
)
buffer_memory_end
=
2
*
1024
*
1024
;
else
buffer_memory_end
=
1
*
1024
*
1024
;
main_memory_start
=
buffer_memory_end;
main_memory_start
+
=
rd_init(main_memory_start, RAMDISK
*
1024
);
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
chr_dev_init();
tty_init();
time_init();
sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sti();
move_to_user_mode();
/
/
切换到用户态
if
(!fork()) {
/
*
创建
0
号进程
*
/
init();
}
for
(;;) pause();
}
void main(void)
/
*
This really IS void, no error here.
*
/
{
/
*
The startup routine assumes (well, ...) this
*
/
/
*
*
Interrupts are still disabled. Do necessary setups, then
*
enable them
*
/
ROOT_DEV
=
ORIG_ROOT_DEV;
drive_info
=
DRIVE_INFO;
memory_end
=
(
1
<<
20
)
+
(EXT_MEM_K<<
10
);
memory_end &
=
0xfffff000
;
if
(memory_end >
16
*
1024
*
1024
)
memory_end
=
16
*
1024
*
1024
;
if
(memory_end >
12
*
1024
*
1024
)
buffer_memory_end
=
4
*
1024
*
1024
;
else
if
(memory_end >
6
*
1024
*
1024
)
buffer_memory_end
=
2
*
1024
*
1024
;
else
buffer_memory_end
=
1
*
1024
*
1024
;
main_memory_start
=
buffer_memory_end;
main_memory_start
+
=
rd_init(main_memory_start, RAMDISK
*
1024
);
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
chr_dev_init();
tty_init();
time_init();
sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sti();
move_to_user_mode();
/
/
切换到用户态
if
(!fork()) {
/
*
创建
0
号进程
*
/
init();
}
for
(;;) pause();
}
__asm__ (
"movl %%esp,%%eax\n\t"
\
"pushl $0x17\n\t"
\
"pushl %%eax\n\t"
\
"pushfl\n\t"
\
"pushl $0x0f\n\t"
\
"pushl $1f\n\t"
\
"iret\n"
\
"1:\tmovl $0x17,%%eax\n\t"
\
"movw %%ax,%%ds\n\t"
\
"movw %%ax,%%es\n\t"
\
"movw %%ax,%%fs\n\t"
\
"movw %%ax,%%gs"
\
:::
"ax"
)
__asm__ (
"movl %%esp,%%eax\n\t"
\
"pushl $0x17\n\t"
\
"pushl %%eax\n\t"
\
"pushfl\n\t"
\
"pushl $0x0f\n\t"
\
"pushl $1f\n\t"
\
"iret\n"
\
"1:\tmovl $0x17,%%eax\n\t"
\
"movw %%ax,%%ds\n\t"
\
"movw %%ax,%%es\n\t"
\
"movw %%ax,%%fs\n\t"
\
"movw %%ax,%%gs"
\
:::
"ax"
)
static char
*
argv_rc[]
=
{
"/bin/sh"
, NULL };
static char
*
envp_rc[]
=
{
"HOME=/"
, NULL };
static char
*
argv[]
=
{
"-/bin/sh"
,NULL };
static char
*
envp[]
=
{
"HOME=/usr/root"
, NULL };
void init(void)
{
int
pid,i;
setup((void
*
) &drive_info);
(void)
open
(
"/dev/tty0"
,O_RDWR,
0
);
/
/
tty0设备是标准输入控制台,句柄为
0
(void) dup(
0
);
(void) dup(
0
);
printf(
"%d buffers = %d bytes buffer space\n\r"
,NR_BUFFERS,
NR_BUFFERS
*
BLOCK_SIZE);
printf(
"Free mem: %d bytes\n\r"
,memory_end
-
main_memory_start);
if
(!(pid
=
fork())) {
/
/
对于被创建的子进程,返回值为
0
,所以
if
里面的语句是在子进程中执行,并打开rc文件并用获得的shell在
/
执行rc里的命令
close(
0
);
/
/
关闭标准输入,所有进程共用文件描述符
if
(
open
(
"/etc/rc"
,O_RDONLY,
0
))
_exit(
1
);
execve(
"/bin/sh"
,argv_rc,envp_rc);
_exit(
2
);
}
if
(pid>
0
)
/
/
fork后对于父进程来说,返回的是子进程的进程号,即
if
语句内是父进程要执行的代码
while
(pid !
=
wait(&i))
/
/
等待子进程退出
/
*
nothing
*
/
;
while
(
1
) {
/
/
如果执行到了这里,就说明子进程已经创建完成退出或者终止,下面是再创建一个子进程,
if
((pid
=
fork())<
0
) {
printf(
"Fork failed in init\r\n"
);
continue
;
}
if
(!pid) {
/
/
创建成功
close(
0
);close(
1
);close(
2
);
setsid();
(void)
open
(
"/dev/tty0"
,O_RDWR,
0
);
(void) dup(
0
);
(void) dup(
0
);
_exit(execve(
"/bin/sh"
,argv,envp));
}
while
(
1
)
if
(pid
=
=
wait(&i))
break
;
printf(
"\n\rchild %d died with code %04x\n\r"
,pid,i);
sync();
}
_exit(
0
);
/
*
NOTE! _exit,
not
exit()
*
/
}
static char
*
argv_rc[]
=
{
"/bin/sh"
, NULL };
static char
*
envp_rc[]
=
{
"HOME=/"
, NULL };
static char
*
argv[]
=
{
"-/bin/sh"
,NULL };
static char
*
envp[]
=
{
"HOME=/usr/root"
, NULL };
void init(void)
{
int
pid,i;
setup((void
*
) &drive_info);
(void)
open
(
"/dev/tty0"
,O_RDWR,
0
);
/
/
tty0设备是标准输入控制台,句柄为
0
(void) dup(
0
);
(void) dup(
0
);
printf(
"%d buffers = %d bytes buffer space\n\r"
,NR_BUFFERS,
NR_BUFFERS
*
BLOCK_SIZE);
printf(
"Free mem: %d bytes\n\r"
,memory_end
-
main_memory_start);
if
(!(pid
=
fork())) {
/
/
对于被创建的子进程,返回值为
0
,所以
if
里面的语句是在子进程中执行,并打开rc文件并用获得的shell在
/
执行rc里的命令
close(
0
);
/
/
关闭标准输入,所有进程共用文件描述符
if
(
open
(
"/etc/rc"
,O_RDONLY,
0
))
_exit(
1
);
execve(
"/bin/sh"
,argv_rc,envp_rc);
_exit(
2
);
}
if
(pid>
0
)
/
/
fork后对于父进程来说,返回的是子进程的进程号,即
if
语句内是父进程要执行的代码
while
(pid !
=
wait(&i))
/
/
等待子进程退出
/
*
nothing
*
/
;
while
(
1
) {
/
/
如果执行到了这里,就说明子进程已经创建完成退出或者终止,下面是再创建一个子进程,
if
((pid
=
fork())<
0
) {
printf(
"Fork failed in init\r\n"
);
continue
;
}
if
(!pid) {
/
/
创建成功
close(
0
);close(
1
);close(
2
);
setsid();
(void)
open
(
"/dev/tty0"
,O_RDWR,
0
);
(void) dup(
0
);
(void) dup(
0
);
_exit(execve(
"/bin/sh"
,argv,envp));
}
while
(
1
)
if
(pid
=
=
wait(&i))
break
;
printf(
"\n\rchild %d died with code %04x\n\r"
,pid,i);
sync();
}
_exit(
0
);
/
*
NOTE! _exit,
not
exit()
*
/
}
void show_task(
int
nr,struct task_struct
*
p)
/
/
nr就是pid
{
int
i,j
=
4096
-
sizeof(struct task_struct);
printk(
"%d: pid=%d, state=%d, "
,nr,p
-
>pid,p
-
>state);
/
/
打印pid与state
i
=
0
;
while
(i<j && !((char
*
)(p
+
1
))[i])
i
+
+
;
printk(
"%d (of %d) chars free in kernel stack\n\r"
,i,j);
/
/
打印栈
}
void show_stat(void)
{
int
i;
for
(i
=
0
;i<NR_TASKS;i
+
+
)
if
(task[i])
show_task(i,task[i]);
}
extern void mem_use(void);
extern
int
timer_interrupt(void);
extern
int
system_call(void);
union task_union {
struct task_struct task;
char stack[PAGE_SIZE];
};
static union task_union init_task
=
{INIT_TASK,};
long
volatile jiffies
=
0
;
long
startup_time
=
0
;
struct task_struct
*
current
=
&(init_task.task);
struct task_struct
*
last_task_used_math
=
NULL;
struct task_struct
*
task[NR_TASKS]
=
{&(init_task.task), };
long
user_stack [ PAGE_SIZE>>
2
] ;
struct {
long
*
a;
short b;
} stack_start
=
{ & user_stack [PAGE_SIZE>>
2
] ,
0x10
};
/
*
*
'math_state_restore()'
saves the current math information
in
the
*
old math state array,
and
gets the new ones
from
the current task
*
/
void math_state_restore()
/
/
进程切换时完成协处理器中寄存器的切换
{
if
(last_task_used_math
=
=
current)
return
;
__asm__(
"fwait"
);
if
(last_task_used_math) {
__asm__(
"fnsave %0"
::
"m"
(last_task_used_math
-
>tss.i387));
}
last_task_used_math
=
current;
if
(current
-
>used_math) {
__asm__(
"frstor %0"
::
"m"
(current
-
>tss.i387));
}
else
{
__asm__(
"fninit"
::);
current
-
>used_math
=
1
;
}
}
/
*
*
'schedule()'
is
the scheduler function. This
is
GOOD CODE! There
*
probably won't be
any
reason to change this, as it should work well
*
in
all
circumstances (ie gives IO
-
bound processes good response etc).
*
The one thing you might take a look at
is
the signal
-
handler code here.
*
*
NOTE!! Task
0
is
the
'idle'
task, which gets called when no other
*
tasks can run. It can
not
be killed,
and
it cannot sleep. The
'state'
*
information
in
task[
0
]
is
never used.
*
/
void schedule(void)
{
int
i,
next
,c;
struct task_struct
*
*
p;
/
*
check alarm, wake up
any
interruptible tasks that have got a signal
*
/
/
*
*
/
for
(p
=
&LAST_TASK ; p > &FIRST_TASK ;
-
-
p)
/
/
从后往前遍历
if
(
*
p) {
/
/
若进程存在
if
((
*
p)
-
>alarm && (
*
p)
-
>alarm < jiffies) {
/
/
若alarm不为空且小于jiffies(此处是
0
)
(
*
p)
-
>signal |
=
(
1
<<(SIGALRM
-
1
));
(
*
p)
-
>alarm
=
0
;
}
if
(((
*
p)
-
>signal & ~(_BLOCKABLE & (
*
p)
-
>blocked)) &&
/
/
进程不理会某些信号;并且进程是可中断睡眠状态
(
*
p)
-
>state
=
=
TASK_INTERRUPTIBLE)
(
*
p)
-
>state
=
TASK_RUNNING;
}
/
*
this
is
the scheduler proper:
*
/
while
(
1
) {
/
/
进行counter的比较,来决定进程的调用
c
=
-
1
;
next
=
0
;
i
=
NR_TASKS;
p
=
&task[NR_TASKS];
while
(
-
-
i) {
if
(!
*
-
-
p)
continue
;
if
((
*
p)
-
>state
=
=
TASK_RUNNING && (
*
p)
-
>counter > c)
c
=
(
*
p)
-
>counter,
next
=
i;
/
/
遍历之后,会将counter的最大值赋给c,并且
next
存着最大counter的pid
}
if
(c)
break
;
for
(p
=
&LAST_TASK ; p > &FIRST_TASK ;
-
-
p)
if
(
*
p)
(
*
p)
-
>counter
=
((
*
p)
-
>counter >>
1
)
+
/
/
counter
=
counter
/
2
+
priority
(
*
p)
-
>priority;
}
switch_to(
next
);
/
/
进程切换
}
/
*
这部分代码的目的是在所有就绪状态的任务进程中筛选出counter值最大的进程
ID
。之后如果counter值不为
0
则进入调度这个进程执行,如果counter值为
0
,则说明所有就绪状态的进程的时间片都已用完,需要重新调整所有进程的时间片。
*
/
/
*
struct {
long
a,b;} __tmp; \
__asm__(
"cmpl %%ecx,_current\n\t"
\
"je 1f\n\t"
\
"movw %%dx,%1\n\t"
\
"xchgl %%ecx,_current\n\t"
\
"ljmp %0\n\t"
\
"cmpl %%ecx,_last_task_used_math\n\t"
\
"jne 1f\n\t"
\
"clts\n"
\
"1:"
\
::
"m"
(
*
&__tmp.a),
"m"
(
*
&__tmp.b), \
"d"
(_TSS(n)),
"c"
((
long
) task[n])); \
}
*
/
int
sys_pause(void)
{
current
-
>state
=
TASK_INTERRUPTIBLE;
schedule();
return
0
;
}
void sleep_on(struct task_struct
*
*
p)
/
/
当p进程想访问cpu的某个资源,但是该资源被占用;
{
struct task_struct
*
tmp;
if
(!p)
return
;
if
(current
=
=
&(init_task.task))
/
/
如果当前进程为
0
号进程时,就返回,不能sleep
panic(
"task[0] trying to sleep"
);
tmp
=
*
p;
*
p
=
current;
/
/
将p赋为当前进程
current
-
>state
=
TASK_UNINTERRUPTIBLE;
schedule();
if
(tmp)
tmp
-
>state
=
0
;
}
void interruptible_sleep_on(struct task_struct
*
*
p)
{
struct task_struct
*
tmp;
if
(!p)
return
;
if
(current
=
=
&(init_task.task))
panic(
"task[0] trying to sleep"
);
tmp
=
*
p;
*
p
=
current;
repeat: current
-
>state
=
TASK_INTERRUPTIBLE;
schedule();
if
(
*
p &&
*
p !
=
current) {
(
*
*
p).state
=
0
;
goto repeat;
}
*
p
=
NULL;
if
(tmp)
tmp
-
>state
=
0
;
}
void wake_up(struct task_struct
*
*
p)
{
if
(p &&
*
p) {
(
*
*
p).state
=
0
;
*
p
=
NULL;
}
}
/
*
*
OK, here are some floppy things that shouldn't be
in
the kernel
*
proper. They are here because the floppy needs a timer,
and
this
*
was the easiest way of doing it.
*
/
static struct task_struct
*
wait_motor[
4
]
=
{NULL,NULL,NULL,NULL};
static
int
mon_timer[
4
]
=
{
0
,
0
,
0
,
0
};
static
int
moff_timer[
4
]
=
{
0
,
0
,
0
,
0
};
unsigned char current_DOR
=
0x0C
;
int
ticks_to_floppy_on(unsigned
int
nr)
{
extern unsigned char selected;
unsigned char mask
=
0x10
<< nr;
if
(nr>
3
)
panic(
"floppy_on: nr>3"
);
moff_timer[nr]
=
10000
;
/
*
100
s
=
very big :
-
)
*
/
cli();
/
*
use floppy_off to turn it off
*
/
mask |
=
current_DOR;
if
(!selected) {
mask &
=
0xFC
;
mask |
=
nr;
}
if
(mask !
=
current_DOR) {
outb(mask,FD_DOR);
if
((mask ^ current_DOR) &
0xf0
)
mon_timer[nr]
=
HZ
/
2
;
else
if
(mon_timer[nr] <
2
)
mon_timer[nr]
=
2
;
current_DOR
=
mask;
}
sti();
return
mon_timer[nr];
}
void floppy_on(unsigned
int
nr)
{
cli();
while
(ticks_to_floppy_on(nr))
sleep_on(nr
+
wait_motor);
sti();
}
void floppy_off(unsigned
int
nr)
{
moff_timer[nr]
=
3
*
HZ;
}
void do_floppy_timer(void)
{
int
i;
unsigned char mask
=
0x10
;
for
(i
=
0
; i<
4
; i
+
+
,mask <<
=
1
) {
if
(!(mask & current_DOR))
continue
;
if
(mon_timer[i]) {
if
(!
-
-
mon_timer[i])
wake_up(i
+
wait_motor);
}
else
if
(!moff_timer[i]) {
current_DOR &
=
~mask;
outb(current_DOR,FD_DOR);
}
else
moff_timer[i]
-
-
;
}
}
static struct timer_list {
long
jiffies;
void (
*
fn)();
struct timer_list
*
next
;
} timer_list[TIME_REQUESTS],
*
next_timer
=
NULL;
void add_timer(
long
jiffies, void (
*
fn)(void))
{
struct timer_list
*
p;
if
(!fn)
return
;
cli();
if
(jiffies <
=
0
)
(fn)();
else
{
for
(p
=
timer_list ; p < timer_list
+
TIME_REQUESTS ; p
+
+
)
if
(!p
-
>fn)
break
;
if
(p >
=
timer_list
+
TIME_REQUESTS)
panic(
"No more time requests free"
);
p
-
>fn
=
fn;
p
-
>jiffies
=
jiffies;
p
-
>
next
=
next_timer;
next_timer
=
p;
while
(p
-
>
next
&& p
-
>
next
-
>jiffies < p
-
>jiffies) {
p
-
>jiffies
-
=
p
-
>
next
-
>jiffies;
fn
=
p
-
>fn;
p
-
>fn
=
p
-
>
next
-
>fn;
p
-
>
next
-
>fn
=
fn;
jiffies
=
p
-
>jiffies;
p
-
>jiffies
=
p
-
>
next
-
>jiffies;
p
-
>
next
-
>jiffies
=
jiffies;
p
=
p
-
>
next
;
}
}
sti();
}
void do_timer(
long
cpl)
{
extern
int
beepcount;
extern void sysbeepstop(void);
if
(beepcount)
if
(!
-
-
beepcount)
sysbeepstop();
if
(cpl)
current
-
>utime
+
+
;
else
current
-
>stime
+
+
;
if
(next_timer) {
next_timer
-
>jiffies
-
-
;
while
(next_timer && next_timer
-
>jiffies <
=
0
) {
void (
*
fn)(void);
fn
=
next_timer
-
>fn;
next_timer
-
>fn
=
NULL;
next_timer
=
next_timer
-
>
next
;
(fn)();
}
}
if
(current_DOR &
0xf0
)
do_floppy_timer();
if
((
-
-
current
-
>counter)>
0
)
return
;
current
-
>counter
=
0
;
if
(!cpl)
return
;
schedule();
}
int
sys_alarm(
long
seconds)
{
int
old
=
current
-
>alarm;
if
(old)
old
=
(old
-
jiffies)
/
HZ;
current
-
>alarm
=
(seconds>
0
)?(jiffies
+
HZ
*
seconds):
0
;
return
(old);
}
int
sys_getpid(void)
{
return
current
-
>pid;
}
int
sys_getppid(void)
{
return
current
-
>father;
}
int
sys_getuid(void)
{
return
current
-
>uid;
}
int
sys_geteuid(void)
{
return
current
-
>euid;
}
int
sys_getgid(void)
{
return
current
-
>gid;
}
int
sys_getegid(void)
{
return
current
-
>egid;
}
int
sys_nice(
long
increment)
{
if
(current
-
>priority
-
increment>
0
)
current
-
>priority
-
=
increment;
return
0
;
}
void sched_init(void)
{
int
i;
struct desc_struct
*
p;
if
(sizeof(struct sigaction) !
=
16
)
panic(
"Struct sigaction MUST be 16 bytes"
);
set_tss_desc(gdt
+
FIRST_TSS_ENTRY,&(init_task.task.tss));
set_ldt_desc(gdt
+
FIRST_LDT_ENTRY,&(init_task.task.ldt));
p
=
gdt
+
2
+
FIRST_TSS_ENTRY;
for
(i
=
1
;i<NR_TASKS;i
+
+
) {
task[i]
=
NULL;
p
-
>a
=
p
-
>b
=
0
;
p
+
+
;
p
-
>a
=
p
-
>b
=
0
;
p
+
+
;
}
/
*
Clear NT, so that we won't have troubles with that later on
*
/
__asm__(
"pushfl ; andl $0xffffbfff,(%esp) ; popfl"
);
ltr(
0
);
lldt(
0
);
outb_p(
0x36
,
0x43
);
/
*
binary, mode
3
, LSB
/
MSB, ch
0
*
/
outb_p(LATCH &
0xff
,
0x40
);
/
*
LSB
*
/
outb(LATCH >>
8
,
0x40
);
/
*
MSB
*
/
set_intr_gate(
0x20
,&timer_interrupt);
outb(inb_p(
0x21
)&~
0x01
,
0x21
);
set_system_gate(
0x80
,&system_call);
}
void show_task(
int
nr,struct task_struct
*
p)
/
/
nr就是pid
{
int
i,j
=
4096
-
sizeof(struct task_struct);
printk(
"%d: pid=%d, state=%d, "
,nr,p
-
>pid,p
-
>state);
/
/
打印pid与state
i
=
0
;
while
(i<j && !((char
*
)(p
+
1
))[i])
i
+
+
;
printk(
"%d (of %d) chars free in kernel stack\n\r"
,i,j);
/
/
打印栈
}
void show_stat(void)
{
int
i;
for
(i
=
0
;i<NR_TASKS;i
+
+
)
if
(task[i])
show_task(i,task[i]);
}
extern void mem_use(void);
extern
int
timer_interrupt(void);
extern
int
system_call(void);
union task_union {
struct task_struct task;
char stack[PAGE_SIZE];
};
static union task_union init_task
=
{INIT_TASK,};
long
volatile jiffies
=
0
;
long
startup_time
=
0
;
struct task_struct
*
current
=
&(init_task.task);
struct task_struct
*
last_task_used_math
=
NULL;
struct task_struct
*
task[NR_TASKS]
=
{&(init_task.task), };
long
user_stack [ PAGE_SIZE>>
2
] ;
struct {
long
*
a;
short b;
} stack_start
=
{ & user_stack [PAGE_SIZE>>
2
] ,
0x10
};
/
*
*
'math_state_restore()'
saves the current math information
in
the
*
old math state array,
and
gets the new ones
from
the current task
*
/
void math_state_restore()
/
/
进程切换时完成协处理器中寄存器的切换
{
if
(last_task_used_math
=
=
current)
return
;
__asm__(
"fwait"
);
if
(last_task_used_math) {
__asm__(
"fnsave %0"
::
"m"
(last_task_used_math
-
>tss.i387));
}
last_task_used_math
=
current;
if
(current
-
>used_math) {
__asm__(
"frstor %0"
::
"m"
(current
-
>tss.i387));
}
else
{
__asm__(
"fninit"
::);
current
-
>used_math
=
1
;
}
}
/
*
*
'schedule()'
is
the scheduler function. This
is
GOOD CODE! There
*
probably won't be
any
reason to change this, as it should work well
*
in
all
circumstances (ie gives IO
-
bound processes good response etc).
*
The one thing you might take a look at
is
the signal
-
handler code here.
*
*
NOTE!! Task
0
is
the
'idle'
task, which gets called when no other
*
tasks can run. It can
not
be killed,
and
it cannot sleep. The
'state'
*
information
in
task[
0
]
is
never used.
*
/
void schedule(void)
{
int
i,
next
,c;
struct task_struct
*
*
p;
/
*
check alarm, wake up
any
interruptible tasks that have got a signal
*
/
/
*
*
/
for
(p
=
&LAST_TASK ; p > &FIRST_TASK ;
-
-
p)
/
/
从后往前遍历
if
(
*
p) {
/
/
若进程存在
if
((
*
p)
-
>alarm && (
*
p)
-
>alarm < jiffies) {
/
/
若alarm不为空且小于jiffies(此处是
0
)
(
*
p)
-
>signal |
=
(
1
<<(SIGALRM
-
1
));
(
*
p)
-
>alarm
=
0
;
}
if
(((
*
p)
-
>signal & ~(_BLOCKABLE & (
*
p)
-
>blocked)) &&
/
/
进程不理会某些信号;并且进程是可中断睡眠状态
(
*
p)
-
>state
=
=
TASK_INTERRUPTIBLE)
(
*
p)
-
>state
=
TASK_RUNNING;
}
/
*
this
is
the scheduler proper:
*
/
while
(
1
) {
/
/
进行counter的比较,来决定进程的调用
c
=
-
1
;
next
=
0
;
i
=
NR_TASKS;
p
=
&task[NR_TASKS];
while
(
-
-
i) {
if
(!
*
-
-
p)
continue
;
if
((
*
p)
-
>state
=
=
TASK_RUNNING && (
*
p)
-
>counter > c)
c
=
(
*
p)
-
>counter,
next
=
i;
/
/
遍历之后,会将counter的最大值赋给c,并且
next
存着最大counter的pid
}
if
(c)
break
;
for
(p
=
&LAST_TASK ; p > &FIRST_TASK ;
-
-
p)
if
(
*
p)
(
*
p)
-
>counter
=
((
*
p)
-
>counter >>
1
)
+
/
/
counter
=
counter
/
2
+
priority
(
*
p)
-
>priority;
}
switch_to(
next
);
/
/
进程切换
}
/
*
这部分代码的目的是在所有就绪状态的任务进程中筛选出counter值最大的进程
ID
。之后如果counter值不为
0
则进入调度这个进程执行,如果counter值为
0
,则说明所有就绪状态的进程的时间片都已用完,需要重新调整所有进程的时间片。
*
/
/
*
struct {
long
a,b;} __tmp; \
__asm__(
"cmpl %%ecx,_current\n\t"
\
"je 1f\n\t"
\
"movw %%dx,%1\n\t"
\
"xchgl %%ecx,_current\n\t"
\
"ljmp %0\n\t"
\
"cmpl %%ecx,_last_task_used_math\n\t"
\
"jne 1f\n\t"
\
"clts\n"
\
"1:"
\
::
"m"
(
*
&__tmp.a),
"m"
(
*
&__tmp.b), \
"d"
(_TSS(n)),
"c"
((
long
) task[n])); \
}
*
/
int
sys_pause(void)
{
current
-
>state
=
TASK_INTERRUPTIBLE;
schedule();
return
0
;
}
void sleep_on(struct task_struct
*
*
p)
/
/
当p进程想访问cpu的某个资源,但是该资源被占用;
{
struct task_struct
*
tmp;
if
(!p)
return
;
if
(current
=
=
&(init_task.task))
/
/
如果当前进程为
0
号进程时,就返回,不能sleep
panic(
"task[0] trying to sleep"
);
tmp
=
*
p;
*
p
=
current;
/
/
将p赋为当前进程
current
-
>state
=
TASK_UNINTERRUPTIBLE;
schedule();
if
(tmp)
tmp
-
>state
=
0
;
}
void interruptible_sleep_on(struct task_struct
*
*
p)
{
struct task_struct
*
tmp;
if
(!p)
return
;
if
(current
=
=
&(init_task.task))
panic(
"task[0] trying to sleep"
);
tmp
=
*
p;
*
p
=
current;
repeat: current
-
>state
=
TASK_INTERRUPTIBLE;
schedule();
if
(
*
p &&
*
p !
=
current) {
(
*
*
p).state
=
0
;
goto repeat;
}
*
p
=
NULL;
if
(tmp)
tmp
-
>state
=
0
;
}
void wake_up(struct task_struct
*
*
p)
{
if
(p &&
*
p) {
(
*
*
p).state
=
0
;
*
p
=
NULL;
}
}
/
*
*
OK, here are some floppy things that shouldn't be
in
the kernel
*
proper. They are here because the floppy needs a timer,
and
this
*
was the easiest way of doing it.
*
/
static struct task_struct
*
wait_motor[
4
]
=
{NULL,NULL,NULL,NULL};
static
int
mon_timer[
4
]
=
{
0
,
0
,
0
,
0
};
static
int
moff_timer[
4
]
=
{
0
,
0
,
0
,
0
};
unsigned char current_DOR
=
0x0C
;
int
ticks_to_floppy_on(unsigned
int
nr)
{
extern unsigned char selected;
unsigned char mask
=
0x10
<< nr;
if
(nr>
3
)
panic(
"floppy_on: nr>3"
);
moff_timer[nr]
=
10000
;
/
*
100
s
=
very big :
-
)
*
/
cli();
/
*
use floppy_off to turn it off
*
/
mask |
=
current_DOR;
if
(!selected) {
mask &
=
0xFC
;
mask |
=
nr;
}
if
(mask !
=
current_DOR) {
outb(mask,FD_DOR);
if
((mask ^ current_DOR) &
0xf0
)
mon_timer[nr]
=
HZ
/
2
;
else
if
(mon_timer[nr] <
2
)
mon_timer[nr]
=
2
;
current_DOR
=
mask;
}
sti();
return
mon_timer[nr];
}
void floppy_on(unsigned
int
nr)
{
cli();
while
(ticks_to_floppy_on(nr))
sleep_on(nr
+
wait_motor);
sti();
}
void floppy_off(unsigned
int
nr)
{
moff_timer[nr]
=
3
*
HZ;
}
void do_floppy_timer(void)
{
int
i;
unsigned char mask
=
0x10
;
for
(i
=
0
; i<
4
; i
+
+
,mask <<
=
1
) {
if
(!(mask & current_DOR))
continue
;
if
(mon_timer[i]) {
if
(!
-
-
mon_timer[i])
wake_up(i
+
wait_motor);
}
else
if
(!moff_timer[i]) {
current_DOR &
=
~mask;
outb(current_DOR,FD_DOR);
}
else
moff_timer[i]
-
-
;
}
}
static struct timer_list {
long
jiffies;
void (
*
fn)();
struct timer_list
*
next
;
} timer_list[TIME_REQUESTS],
*
next_timer
=
NULL;
void add_timer(
long
jiffies, void (
*
fn)(void))
{
struct timer_list
*
p;
if
(!fn)
return
;
cli();
if
(jiffies <
=
0
)
(fn)();
else
{
for
(p
=
timer_list ; p < timer_list
+
TIME_REQUESTS ; p
+
+
)
if
(!p
-
>fn)
break
;
if
(p >
=
timer_list
+
TIME_REQUESTS)
panic(
"No more time requests free"
);
p
-
>fn
=
fn;
p
-
>jiffies
=
jiffies;
p
-
>
next
=
next_timer;
next_timer
=
p;
while
(p
-
>
next
&& p
-
>
next
-
>jiffies < p
-
>jiffies) {
p
-
>jiffies
-
=
p
-
>
next
-
>jiffies;
fn
=
p
-
>fn;
p
-
>fn
=
p
-
>
next
-
>fn;
p
-
>
next
-
>fn
=
fn;
jiffies
=
p
-
>jiffies;
p
-
>jiffies
=
p
-
>
next
-
>jiffies;
p
-
>
next
-
>jiffies
=
jiffies;
p
=
p
-
>
next
;
}
}
sti();
}
void do_timer(
long
cpl)
{
extern
int
beepcount;
extern void sysbeepstop(void);
if
(beepcount)
if
(!
-
-
beepcount)
sysbeepstop();
if
(cpl)
current
-
>utime
+
+
;
else
current
-
>stime
+
+
;
if
(next_timer) {
next_timer
-
>jiffies
-
-
;
while
(next_timer && next_timer
-
>jiffies <
=
0
) {
void (
*
fn)(void);
fn
=
next_timer
-
>fn;
next_timer
-
>fn
=
NULL;
next_timer
=
next_timer
-
>
next
;
(fn)();
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课