|
ͬ�ô�ѧ |
|
Linux����ϵͳʵ��ԭ�� |
|
�ں˳��� |
|
|
|
�Ծ� |
|
2017/9/18 |
|
Linux 0.12���ں���ע�ͳ��� |
|
|
Ŀ¼
6.1 ����6 ‑1 linux/boot/bootsect.S
6.2 ���� 6‑2 linux/boot/setup.S
8.1 ����8-1 linux/kernel/asm.s
8.2 ����8-2 linux/kernel/traps.c
8.3 ����8-3 linux/kernel/sys_call.s
8.4 ����8-4 linux/kernel/mktime.c����
8.5 ����8-5 linux/kernel/sched.c
8.6 ����8-6 linux/kernel/signal.c
8.7 ����8-7 linux/kernel/exit.c
8.8 ����8-8 linux/kernel/fork.c
8.9 ����8-9 linux/kernel/sys.c����
8.10 ����8-10 linux/kernel/vsprintf.c
8.11 ����8-11 linux/kernel/printk.c
8.12 ����8-12 linux/kernel/panic.c
9.1 ����9-1 linux/kernel/blk_drv/blk.h
9.2 ����9-2 linux/kernel/blk_drv/hd.c
9.3 ����9-3 linux/kernel/blk_drv/ll_rw_blk.c
9.4 ����9-4 linux/kernel/blk_drv/ramdisk.c
9.5 ����9-5 linux/kernel/blk_drv/floppy.c
10.1 ����10-1 linux/kernel/chr_drv/keyboard.S
10.2 ����10-2 linux/kernel/chr_drv/console.c
10.3 ����10-3 linux/kernel/chr_drv/serial.c
10.4 ����10-4 linux/kernel/chr_drv/rs_io.s
10.5 ����10-5 linux/kernel/chr_drv/tty_io.c
10.6 ����10-6 linux/kernel/chr_drv/tty_ioctl.c
11.1 ����11-1 linux/kernel/math/math_emulate.c
11.2 ����11-2 linux/kernel/math/error.c
11.3 ����11-3 linux/kernel/math/ea.c
11.4 ����11-4 linux/kernel/math/convert.c
11.5 ����11-5 linux/kernel/math/add.c
11.6 ����11-6 linux/kernel/math/compare.c
11.7 ����11-7 linux/kernel/math/get_put.c
11.8 ����11-8 linux/kernel/math/mul.c
11.9 ����11-9 linux/kernel/math/div.c
12.1 ����12-1 linux/fs/buffer.c
12.2 ���� 12-2 linux/fs/bitmap.c
12.3 ����12-3 linux/fs/truncate.c
12.4 ����12-4 linux/fs/inode.c
12.5 ����12-5 linux/fs/super.c
12.6 ����12-6 linux/fs/namei.c
12.7 ����12-7 linux/fs/file_table.c
12.8 ����12-8 linux/fs/block_dev.c
12.9 ����12-9 linux/fs/file_dev.c
12.10 ����12-10 linux/fs/pipe.c
12.11 ����12-11 linux/fs/char_dev.c
12.12 ����12-12 linux/fs/read_write.c
12.13 ����12-13 linux/fs/open.c
12.14 ����12-14 linux/fs/exec.c
12.15 ����12-15 linux/fs/stat.c
12.16 ����12-16 linux/fs/fcntl.c
12.17 ����12-17 linux/fs/ioctl.c
12.18 ����12-18 linux/fs/select.c
13.1 ����13-1 linux/mm/memory.c
14.1 ����14-1 linux/include/a.out.h
14.2 ����14-2 linux/include/const.h
14.3 ����14-3 linux/include/ctype.h
14.4 ����14-4 linux/include/errno.h
14.5 ����14-5 linux/include/fcntl.h
14.6 ����14-6 linux/include/signal.h
14.7 ����14-7 linux/include/stdarg.h
14.8 ����14-8 linux/include/stddef.h
14.9 ����14-9 linux/include/string.h
14.10 ����14-10 linux/include/termios.h
14.11 ����14-11 linux/include/time.h
14.12 ����14-12 linux/include/unistd.h
14.13 ����14-13 linux/include/utime.h
14.14 ����14-14 linux/include/asm/io.h
14.15 ����14-15 linux/include/asm/memory.h
14.16 ����14-16 linux/include/asm/segment.h
14.17 ����14-17 linux/include/asm/system.h
14.18 ����14-18 linux/include/linux/config.h
14.19 ����14-19 linux/include/linux/fdreg.h
14.20 ����14-20 linux/include/linux/fs.h
14.21 ����14-21 linux/include/linux/hdreg.h
14.22 ����14-22 linux/include/linux/head.h
14.23 ����14-23 linux/include/linux/kernel.h
14.24 ����14-24 linux/include/linux/math_emu.h
14.25 ����14-25 linux/include/linux/mm.h
14.26 ����14-26 linux/include/linux/sched.h
14.27 ����14-27 linux/include/linux/sys.h
14.28 ����14-28 linux/include/linux/tty.h
14.29 ����14-29 linux/include/sys/param.h
14.30 ����14-30 linux/include/sys/resource.h
14.31 ����14-31 linux/include/sys/stat.h
14.32 ����14-32 linux/include/sys/time.h
14.33 ����14-33 linux/include/sys/times.h
14.34 ����14-34 linux/include/sys/types.h
14.35 ����14-35 linux/include/sys/utsname.h
14.36 ����14-36 linux/include/sys/wait.h
15.1 ����15-1 linux/lib/_exit.c
15.2 ����15-2 linux/lib/close.c
15.3 ����15-3 linux/lib/ctype.c
15.5 ����15-5 linux/lib/errno.c
15.6 ����15-6 linux/lib/execve.c
15.7 ����15-7 linux/lib/malloc.c
15.8 ����15-8 linux/lib/open.c
15.9 ����15-9 linux/lib/setsid.c
15.10 ����15-10 linux/lib/string.c
15.11 ����15-11 linux/lib/wait.c
1 #
2 # if you want the ram-disk device, define this to be the
3 # size in blocks.
4 #
# �����Ҫʹ��RAM��(RAMDISK)�豸�Ļ��Ͷ����Ĵ�С������Ĭ��RAMDISKû�ж��壨ע�͵��ˣ���
# ����gcc����ʱ�����ѡ��'-DRAMDISK=512'���μ���13�С�
5 RAMDISK = #-DRAMDISK=512
7 AS86 =as86 -0 -a # 8086���������������������б���Ľ��ܡ�����IJ�������ֱ�
8 LD86 =ld86 -0 # �ǣ�-0 ����8086Ŀ�����-a ������gas��gld���ּ��ݵĴ��롣
10 AS =gas # GNU���������������������б���Ľ��ܡ�
11 LD =gld
# ������GNU������gld����ʱ�õ���ѡ������ǣ�-s ����ļ���ʡ�����еķ�����Ϣ��-x ɾ��
# ���оֲ����ţ�-M ��ʾ��Ҫ�ڱ�����豸(��ʾ��)�ϴ�ӡ����ӳ��(link map)����ָ�����ӳ���
# ������һ���ڴ��ַӳ�������г��˳����װ�뵽�ڴ��е�λ����Ϣ������������������Ϣ��
# • Ŀ���ļ���������Ϣӳ�䵽�ڴ��е�λ�ã�
# • ����������η��ã�
# • �����а����������ļ���Ա�������õķ��š�
12 LDFLAGS =-s -x -M
# gcc��GNU C���������������UNIX��Ľű�(script)������ԣ������ö���ı�ʶ��ʱ������ǰ
# �����$���Ų���������ס��ʶ����
13 CC =gcc $(RAMDISK)
# ����ָ��gccʹ�õ�ѡ�ǰһ������'\'���ű�ʾ��һ�������С�ѡ���Ϊ��-Wall ��ӡ����
# ������Ϣ��-O �Դ�������Ż���'-f��־'ָ��������صı����־������-fstrength-reduce��
# ���Ż�ѭ����䣻-fcombine-regs����ָ������������ϱ���ΰѸ���һ���Ĵ�������һ���Ĵ�
# ����ָ�������һ��-fomit-frame-pointer ָ����������ָ֡�루Frame pointer���ĺ�����Ҫ
# ��ָ֡�뱣���ڼĴ����С������ں����п��Ա����ָ֡��IJ�����ά����-mstring-insns ��
# Linus��ѧϰgcc������ʱΪgcc���ӵ�ѡ�����gcc-1.40�ڸ��ƽṹ�Ȳ���ʱʹ��386 CPU��
# �ַ���ָ�����ȥ����
14 CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \
15 -fcombine-regs -mstring-insns
# ����cpp��gcc��ǰ(Ԥ)����������ǰ���������ڽ��г����еĺ��滻�������������봦���Լ�
# ������ָ���ļ������ݣ�����ʹ��'#include'ָ�����ļ�����������Դ�����ļ��������Է���'#'
# ��ʼ���о���Ҫ��ǰ���������д���������������'#define'����ĺ궼��ʹ���䶨�岿���滻����
# ����������'#if'��'#ifdef'��'#ifndef'��'#endif'�������б�������ȷ���Ƿ������ָ����Χ��
# ����䡣
# '-nostdinc -Iinclude'�����Dz�Ҫ������ͷ�ļ�Ŀ¼�е��ļ���������ϵͳ/usr/include/Ŀ¼
# �µ�ͷ�ļ�������ʹ��'-I'ѡ��ָ����Ŀ¼�������ڵ�ǰĿ¼������ͷ�ļ���
16 CPP =cpp -nostdinc -Iinclude
18 #
19 # ROOT_DEV specifies the default root-device when making the image.
20 # This can be either FLOPPY, /dev/xxxx or empty, in which case the
21 # default of /dev/hd6 is used by 'build'.
22 #
# ROOT_DEVָ���ڴ����ں�ӳ��(image)�ļ�ʱ��ʹ�õ�Ĭ�ϸ��ļ�ϵͳ��
# �ڵ��豸�������������(FLOPPY)��/dev/xxxx���߸ɴ���ţ�����ʱ
# build������tools/Ŀ¼�У���ʹ��Ĭ��ֵ/dev/hd6��
#
# ����/dev/hd6��Ӧ��2��Ӳ�̵ĵ�1������������Linus����Linux�ں�ʱ�Լ��Ļ����ϸ�
# �ļ�ϵͳ���ڵķ���λ�á�/dev/hd2��ʾ�ѵ�1��Ӳ�̵ĵ�2��������������������
23 ROOT_DEV=/dev/hd6
24 SWAP_DEV=/dev/hd2
# ������kernelĿ¼��mmĿ¼��fsĿ¼��������Ŀ������ļ���Ϊ�˷������������ォ������
# ARCHIVES���鵵�ļ�����ʶ����ʾ��
26 ARCHIVES=kernel/kernel.o mm/mm.o fs/fs.o
# ����ַ��豸���ļ���'.a'��ʾ���ļ��Ǹ��鵵�ļ���Ҳ�������������ִ�ж����ƴ����ӳ���
# ���ϵĿ��ļ���ͨ������GNU��ar�������ɡ�ar��GNU�Ķ������ļ������������ڴ�������
# �Լ��ӹ鵵�ļ��г�ȡ�ļ���
27 DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a
28 MATH =kernel/math/math.a # ��ѧ������ļ���
29 LIBS =lib/lib.a # ��lib/Ŀ¼�е��ļ����������ɵ�ͨ�ÿ��ļ���
# ������make��ʽ����ʽ��������ָʾmake���������������е�'.c'�ļ���������'.s'
# ������':'��ʾ�����Ǹù������������ʾ��gcc����ǰ��CFLAGS��ָ����ѡ���Լ���ʹ
# ��include/Ŀ¼�е�ͷ�ļ������ʵ��ر�����л���ֹͣ��-S�����Ӷ�����������ĸ���C
# �ļ���Ӧ�Ļ��������ʽ�Ĵ����ļ���Ĭ��������������Ļ������ļ���ԭC�ļ���ȥ��'.c'��
# �ټ���'.s'����'-o'��ʾ���������ļ�����ʽ������'$*.s'����'$@'�����Զ�Ŀ�������'$<'
# ������һ���Ⱦ����������T�Ƿ�������'*.c'���ļ���
# ������3����ͬ����ֱ����ڲ�ͬ�IJ���Ҫ����Ŀ����.s�ļ�����Դ�ļ���.c�ļ����ʹ
# �õ�һ��������Ŀ¼��.o����ԭ�ļ���.s����ʹ�õ�2��������Ŀ����.o�ļ���ԭ�ļ�
# ��c�ļ������ֱ��ʹ�õ�3������
31 .c.s:
32 $(CC) $(CFLAGS) \
33 -nostdinc -Iinclude -S -o $*.s $<
# ��ʾ������.s�������ļ������.oĿ���ļ��� �����ʾʹ��gas������������������.o
# Ŀ���ļ���-c ��ʾֻ������࣬�����������Ӳ�����
34 .s.o:
35 $(AS) -c -o $*.o $<
# �������棬*.c�ļ�-��*.oĿ���ļ��������ʾʹ��gcc��C�����ļ������Ŀ���ļ��������ӡ�
36 .c.o:
37 $(CC) $(CFLAGS) \
38 -nostdinc -Iinclude -c -o $*.o $<
# ����'all'��ʾ����Makefile��֪������Ŀ�ꡣ���T��Image�ļ����������ɵ�Image�ļ�
# ��������������ӳ���ļ�bootimage��������д�����̾Ϳ���ʹ�ø���������Linuxϵͳ�ˡ���
# Linux�½�Imageд�����̵�����μ�46�С�DOSϵͳ�¿���ʹ������rawrite.exe��
40 all: Image
# ˵��Ŀ�꣨Image�ļ�������ð�ź����4��Ԫ�ز������ֱ���boot/Ŀ¼�е�bootsect��setup
# �ļ���tools/Ŀ¼�е�system��build�ļ���42--43������ִ�е����42�б�ʾʹ��toolsĿ
# ¼�µ�build���߳��������˵��������ɣ���bootsect��setup��system�ļ���$(ROOT_DEV)
# Ϊ���ļ�ϵͳ�豸��װ���ں�ӳ���ļ�Image����43�е�syncͬ����������ʹ�������������д��
# �����³����顣
42 Image: boot/bootsect boot/setup tools/system tools/build
43 tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) \
44 $(SWAP_DEV) > Image
45 sync
# ��ʾdisk���Ŀ��Ҫ��Image������ddΪUNIX���������һ���ļ�������ѡ�����ת����
# ʽ����bs=��ʾһ�ζ�/д���ֽ�����if=��ʾ������ļ���of=��ʾ��������ļ�������/dev/PS0��
# ָ��һ������������(�豸�ļ�)����Linuxϵͳ��ʹ��/dev/fd0��
47 disk: Image
48 dd bs=8192 if=Image of=/dev/PS0
50 tools/build: tools/build.c # ��toolsĿ¼�µ�build.c��������ִ�г���build��
51 $(CC) $(CFLAGS) \
52 -o tools/build tools/build.c # ��������ִ�г���build�����
54 boot/head.o: boot/head.s # �������������.s.o��������head.oĿ���ļ���
# ��ʾtoolsĿ¼�е�system�ļ�Ҫ��ð���ұ����е�Ԫ�����ɡ�56--61��������system�����
# ���� > System.map ��ʾgld��Ҫ������ӳ���ض�������System.map�ļ��С�
# ����System.map�ļ�����;�μ�ע�ͺ��˵����
56 tools/system: boot/head.o init/main.o \
57 $(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)
58 $(LD) $(LDFLAGS) boot/head.o init/main.o \
59 $(ARCHIVES) \
60 $(DRIVERS) \
61 $(MATH) \
62 $(LIBS) \
63 -o tools/system > System.map
# ��ѧЭ���������ļ�math.a��64���ϵ�����ʵ�֣�����kernel/math/Ŀ¼������make���߳���
65 kernel/math/math.a:
66 (cd kernel/math; make)
68 kernel/blk_drv/blk_drv.a: # ���ɿ��豸���ļ�blk_drv.a�����к��п��ض�λĿ���ļ���
69 (cd kernel/blk_drv; make)
71 kernel/chr_drv/chr_drv.a: # �����ַ��豸�����ļ�chr_drv.a��
72 (cd kernel/chr_drv; make)
74 kernel/kernel.o: # �ں�Ŀ��ģ��kernel.o
75 (cd kernel; make)
77 mm/mm.o: # �ڴ����ģ��mm.o
78 (cd mm; make)
80 fs/fs.o: # �ļ�ϵͳĿ��ģ��fs.o
81 (cd fs; make)
83 lib/lib.a: # �⺯��lib.a
84 (cd lib; make)
86 boot/setup: boot/setup.s # ���↑ʼ��������ʹ��8086����������
87 $(AS86) -o boot/setup.o boot/setup.s # ��setup.s�ļ����б�������setup�ļ���
88 $(LD86) -s -o boot/setup boot/setup.o # -s ѡ���ʾҪȥ��Ŀ���ļ��еķ�����Ϣ��
90 boot/setup.s: boot/setup.S include/linux/config.h # ִ��C����Ԥ�������滻*.S��
91 $(CPP) -traditional boot/setup.S -o boot/setup.s # ���еĺ����ɶ�Ӧ��*.s�ļ���
92
93 boot/bootsect.s: boot/bootsect.S include/linux/config.h
94 $(CPP) -traditional boot/bootsect.S -o boot/bootsect.s
95
96 boot/bootsect: boot/bootsect.s # ͬ�ϡ�����bootsect.o���������顣
97 $(AS86) -o boot/bootsect.o boot/bootsect.s
98 $(LD86) -s -o boot/bootsect boot/bootsect.o
# ��ִ��'make clean'ʱ���ͻ�ִ��98--103���ϵ����ȥ�����б����������ɵ��ļ���
# 'rm'���ļ�ɾ�����ѡ��-f�����Ǻ��Բ����ڵ��ļ������Ҳ���ʾɾ����Ϣ��
100 clean:
101 rm -f Image System.map tmp_make core boot/bootsect boot/setup \
102 boot/bootsect.s boot/setup.s
103 rm -f init/*.o tools/system tools/build boot/*.o
104 (cd mm;make clean) # ����mm/Ŀ¼��ִ�и�Ŀ¼Makefile�ļ��е�clean����
105 (cd fs;make clean)
106 (cd kernel;make clean)
107 (cd lib;make clean)
# �ù�������ִ�������clean����Ȼ���linux/Ŀ¼����ѹ��������'backup.Z'ѹ���ļ���
# 'cd .. '��ʾ�˵�linux/����һ��������Ŀ¼��'tar cf - linux'��ʾ��linux/Ŀ¼ִ��tar�鵵
# ����'-cf'��ʾ��Ҫ�����µĹ鵵�ļ� '| compress -'��ʾ��tar�����ִ��ͨ���ܵ�����('|')
# ���ݸ�ѹ������compress������ѹ�������������backup.Z�ļ���
109 backup: clean
110 (cd .. ; tar cf - linux | compress - > backup.Z)
111 sync # ��ʹ�������������д�̲����´��̳����顣
113 dep:
# ��Ŀ���������ڲ������ļ�֮���������ϵ��������Щ������ϵ��Ϊ����make������������ȷ��
# �Ƿ���Ҫ�ؽ�һ��Ŀ������統ij��ͷ�ļ����Ķ�����make����ͨ�����ɵ�������ϵ������
# �������ͷ�ļ��йص�����*.c�ļ������巽�����£�
# ʹ���ַ����༭����sed��Makefile�ļ������T�DZ��ļ������д��������Ϊɾ����Makefile
# �ļ���'### Dependencies'�к���������У���ɾ���������122��ʼ���ļ�ĩ�������У�������
# һ����ʱ�ļ�tmp_make��Ҳ��114�е����ã���Ȼ���ָ��Ŀ¼�£�init/����ÿһ��C�ļ�����ʵ
# ֻ��һ���ļ�main.c��ִ��gccԤ������������־'-M'����Ԥ��������cpp�������ÿ��Ŀ���ļ�
# ����ԵĹ�������Щ�������make�������ÿһ��Դ�ļ���Ԥ������������һ��������
# �����ʽ������ӦԴ�����ļ���Ŀ���ļ���������������ϵ������Դ�ļ��а���������ͷ�ļ��б���
# Ȼ���Ԥ������������ӵ���ʱ�ļ�tmp_make�У������ʱ�ļ����Ƴ��µ�Makefile�ļ���
# 115���ϵ�'$$i'ʵ������'$($i) '������'$i'�����ǰ���shell����'i'��ֵ��
114 sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
115 (for i in init/*.c;do echo -n "init/";$(CPP) -M $$i;done) >> tmp_make
116 cp tmp_make Makefile
117 (cd fs; make dep) # ��fs/Ŀ¼�µ�Makefile�ļ�Ҳ��ͬ���Ĵ�����
118 (cd kernel; make dep)
119 (cd mm; make dep)
121 ### Dependencies:
122 init/main.o : init/main.c include/unistd.h include/sys/stat.h \
123 include/sys/types.h include/sys/time.h include/time.h include/sys/times.h \
124 include/sys/utsname.h include/sys/param.h include/sys/resource.h \
125 include/utime.h include/linux/tty.h include/termios.h include/linux/sched.h \
126 include/linux/head.h include/linux/fs.h include/linux/mm.h \
127 include/linux/kernel.h include/signal.h include/asm/system.h \
128 include/asm/io.h include/stddef.h include/stdarg.h include/fcntl.h \
129 include/string.h
1 !
2 ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
3 ! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
4 ! versions of linux
! SYS_SIZE��Ҫ���ص�ϵͳģ�鳤�ȣ���λ�ǽڣ�ÿ��16�ֽڡ�0x3000��Ϊ0x30000�ֽ�=196KB��
! ����1024�ֽ�Ϊ1KB�ƣ���Ӧ����192KB�����ڵ�ǰ�ں˰汾����ռ䳤�����㹻�ˡ�����ֵΪ
! 0x8000ʱ����ʾ�ں����Ϊ512KB����Ϊ�ڴ�0x90000����ʼ����ƶ����bootsect��setup
! �Ĵ��룬��˸�ֵ��ó���0x9000����ʾ584KB����
! �����̾��'!'��ֺ�';'��ʾ����ע����俪ʼ��
5 !
! ͷ�ļ�linux/config.h�ж������ں��õ���һЩ�������ź�Linus�Լ�ʹ�õ�Ĭ��Ӳ�̲����顣
! �������ж���������һЩ������
! DEF_SYSSIZE = 0x3000 - Ĭ��ϵͳģ�鳤�ȡ���λ�ǽڣ�ÿ��Ϊ16�ֽڣ�
! DEF_INITSEG = 0x9000 - Ĭ�ϱ���������ƶ�Ŀ�Ķ�λ�ã�
! DEF_SETUPSEG = 0x9020 - Ĭ��setup��������λ�ã�
! DEF_SYSSEG = 0x1000 - Ĭ�ϴӴ��̼���ϵͳģ�鵽�ڴ�Ķ�λ�á�
6 #include <linux/config.h>
7 SYSSIZE = DEF_SYSSIZE ! ����һ����Ż���š�ָ���������Ӻ�systemģ��Ĵ�С��
8 !
9 ! bootsect.s (C) 1991 Linus Torvalds
10 ! modified by Drew Eckhardt
11 !
12 ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
13 ! iself out of the way to address 0x90000, and jumps there.
14 !
15 ! It then loads 'setup' directly after itself (0x90200), and the system
16 ! at 0x10000, using BIOS interrupts.
17 !
18 ! NOTE! currently system is at most 8*65536 bytes long. This should be no
19 ! problem, even in the future. I want to keep it simple. This 512 kB
20 ! kernel size should be enough, especially as this doesn't contain the
21 ! buffer cache as in minix
22 !
23 ! The loader has been made as simple as possible, and continuos
24 ! read errors will result in a unbreakable loop. Reboot by hand. It
25 ! loads pretty fast by getting whole sectors at a time whenever possible.
!
! ������ǰ�����ֵ����ģ�
! bootsect.s (C) 1991 Linus Torvalds
! Drew Eckhardt��
!
! bootsect.s ��ROM BIOS�����ӳ��������0x7c00 (31KB)���������Լ��Ƶ��˵�ַ0x90000
! (576KB)��������ת�����
!
! ��Ȼ��ʹ��BIOS�жϽ�'setup'ֱ�Ӽ��ص��Լ��ĺ���(0x90200)(576.5KB)������system��
! �ص���ַ0x10000����
!
! ע��! Ŀǰ���ں�ϵͳ�������Ϊ(8*65536)(512KB)�ֽڣ���ʹ���ڽ�����ҲӦ��û����
! ��ġ������������ּ����ˡ�����512KB������ں˳���Ӧ���㹻�ˣ�����������û����
! MINIX��һ���������������ٻ��塣
!
! ���س����Ѿ����ù����ˣ����Գ����ض�����������������ѭ����ֻ���ֹ�������ֻҪ���ܣ�
! ͨ��һ�ζ�ȡ���е����������ع��̿������úܿ졣
26
! αָ�α��������.globl��.global���ڶ������ı�ʶ�����ⲿ�Ļ�ȫ�ֵģ����Ҽ�ʹ��
! ʹ��Ҳǿ�����롣 .text��.data��.bss���ڷֱ��嵱ǰ����Ρ����ݶκ�δ��ʼ�����ݶΡ�
! �����Ӷ��Ŀ��ģ��ʱ�����ӳ���ld86����������ǵ����Ѹ���Ŀ��ģ���е���Ӧ�ηֱ�
! ��ϣ��ϲ�����һ������������ζ�������ͬһ�ص���ַ��Χ�У���˱�����ʵ���ϲ��ֶΡ�
! ���⣬�����ð�ŵ��ַ����DZ�ţ����������'begtext:'��
! һ��������ͨ���ɱ�ţ���ѡ����ָ�����Ƿ���ָ�������Ͳ����������ֶ���ɡ����λ��
! һ��ָ��ĵ�һ���ֶΡ�������������λ�õĵ�ַ��ͨ��ָ��һ����תָ���Ŀ��λ�á�
27 .globl begtext, begdata, begbss, endtext, enddata, endbss
28 .text ! �ı��Σ�����Σ���
29 begtext:
30 .data ! ���ݶΡ�
31 begdata:
32 .bss ! δ��ʼ�����ݶΡ�
33 begbss:
34 .text ! �ı��Σ�����Σ���
35
! ����Ⱥ�'='�����'EQU'���ڶ����ʶ��������������ֵ��
36 SETUPLEN = 4 ! nr of setup-sectors
! setup�������ռ�ô���������(setup-sectors)ֵ��
37 BOOTSEG = 0x07c0 ! original address of boot-sector
! bootsect���������ڴ�ԭʼ�ε�ַ��
38 INITSEG = DEF_INITSEG ! we move boot here - out of the way
! ��bootsect�Ƶ�λ��0x90000 - �ܿ�ϵͳģ��ռ�ô���
39 SETUPSEG = DEF_SETUPSEG ! setup starts here
! setup������ڴ�0x90200����ʼ��
40 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).
! systemģ����ص�0x10000��64 KB������
41 ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ֹͣ���صĶε�ַ��
42
43 ! ROOT_DEV & SWAP_DEV are now written by "build".
! ���ļ�ϵͳ�豸��ROOT_DEV�ͽ����豸��SWAP_DEV ������toolsĿ¼�µ�build����д�롣
! �豸��0x306ָ�����ļ�ϵͳ�豸�ǵ�2��Ӳ�̵ĵ�1������������Linus���ڵ�2��Ӳ����
! ��װ��Linux 0.11ϵͳ����������ROOT_DEV������Ϊ0x306���ڱ�������ں�ʱ����Ը���
! �Լ����ļ�ϵͳ�����豸λ��������豸�š�����豸����Linuxϵͳ��ʽ��Ӳ���豸����
! ����ʽ��Ӳ���豸�ž���ֵ�ĺ������£�
! �豸��=���豸��*256 + ���豸�ţ�Ҳ��dev_no = (major<<8) + minor ��
! �����豸�ţ�1-�ڴ�,2-����,3-Ӳ��,4-ttyx,5-tty,6-���п�,7-�������ܵ���
! 0x300 - /dev/hd0 - ����������1��Ӳ�̣�
! 0x301 - /dev/hd1 - ��1���̵ĵ�1��������
! ��
! 0x304 - /dev/hd4 - ��1���̵ĵ�4��������
! 0x305 - /dev/hd5 - ����������2��Ӳ�̣�
! 0x306 - /dev/hd6 - ��2���̵ĵ�1��������
! ��
! 0x309 - /dev/hd9 - ��2���̵ĵ�4��������
! ��Linux�ں�0.95�����Ѿ�ʹ���������ں���ͬ�����������ˡ�
44 ROOT_DEV = 0 ! ���ļ�ϵͳ�豸ʹ����ϵͳ����ʱͬ�����豸��
45 SWAP_DEV = 0 ! �����豸ʹ����ϵͳ����ʱͬ�����豸��
46
! αָ��entry��ʹ���ӳ��������ɵ�ִ�г���a.out���а���ָ���ı�ʶ�����š�������
! ����ִ�п�ʼ�㡣49 -- 58�������ǽ�����(bootsect)��Ŀǰ��λ�� 0x07c0(31KB) �ƶ���
! 0x9000(576KB) ������256�֣�512�ֽڣ���Ȼ����ת���ƶ�������go��Ŵ���Ҳ������
! �����һ��䴦��
47 entry start ! ��֪���ӳ������start��ſ�ʼִ�С�
48 start:
49 mov ax,#BOOTSEG ! ��ds�μĴ�����Ϊ0x7C0��
50 mov ds,ax
51 mov ax,#INITSEG ! ��es�μĴ�����Ϊ0x9000��
52 mov es,ax
53 mov cx,#256 ! �����ƶ�����ֵ=256�֣�512�ֽڣ���
54 sub si,si ! Դ��ַ ds:si = 0x07C0:0x0000
55 sub di,di ! Ŀ�ĵ�ַ es:di = 0x9000:0x0000
56 rep ! �ظ�ִ�в��ݼ�cx��ֵ��ֱ��cx = 0Ϊֹ��
57 movw ! ��movsָ����ڴ�[si]���ƶ�cx���ֵ�[di]����
58 jmpi go,INITSEG ! �μ���ת��Jump Intersegment��������INITSEG
! ָ����ת���Ķε�ַ�����go�Ƕ���ƫ�Ƶ�ַ��
59
! �����濪ʼ��CPU�����ƶ���0x90000λ�ô��Ĵ�����ִ�С�
! ��δ������ü����μĴ���������ջ�Ĵ���ss��sp��ջָ��spֻҪָ��Զ����512�ֽ�ƫ��
! ������ַ0x90200���������ԡ���Ϊ��0x90200��ַ��ʼ����Ҫ����setup������ʱsetup
! �����ԼΪ4�����������spҪָ����ڣ�0x200 + 0x200 * 4 +��ջ��С��λ�ô�������sp
! ����Ϊ 0x9ff00 - 12�����������ȣ�����sp = 0xfef4���ڴ�֮��λ�û���һ���Խ�������
! ����������������˵����ʵ����BIOS�������������ص�0x7c00 ������ִ��Ȩ������������ʱ��
! ss = 0x00��sp = 0xfffe��
! ���⣬��65����pushָ�����������������ʱ�Ѷ�ֵ������ջ�У�Ȼ�������ִ�����жϴŵ�
! ���������ٵ���ջ�������μĴ��� fs��gs��ֵ����109�У����������ڵ�67��68�������
! ��ջ�ε�λ�ã���˳�����ִ��ջ��������֮ǰ��ջ�λָ���ԭλ�ã�����������ƾ��Ǵ���ġ�
! ����������һ��bug�������ķ���֮һ��ȥ����65�У����ѵ�109���ijɡ�mov ax,cs����
60 go: mov ax,cs ! ��ds��es��ss���ó��ƶ���������ڵĶδ�(0x9000)��
61 mov dx,#0xfef4 ! arbitrary value >>512 - disk parm size
62
63 mov ds,ax
64 mov es,ax
65 push ax ! ��ʱ�����ֵ��0x9000������109��ʹ�á�����ͷ!��
66
67 mov ss,ax ! put stack at 0x9ff00 - 12.
68 mov sp,dx
69 /*
70 * Many BIOS's default disk parameter tables will not
71 * recognize multi-sector reads beyond the maximum sector number
72 * specified in the default diskette parameter tables - this may
73 * mean 7 sectors in some cases.
74 *
75 * Since single sector reads are slow and out of the question,
76 * we must take care of this by creating new parameter tables
77 * (for the first disk) in RAM. We will set the maximum sector
78 * count to 18 - the most we will encounter on an HD 1.44.
79 *
80 * High doesn't hurt. Low does.
81 *
82 * Segments are as follows: ds=es=ss=cs - INITSEG,
83 * fs = 0, gs = parameter table segment
84 */
/*
* ���ڶ���������������������������Ĭ�ϴ��̲�������ָ�������������ʱ��
* �ܶ�BIOS�����ܽ�����ȷʶ����ijЩ�������7��������
*
* ���ڵ�����������̫���������Կ��ǣ�������DZ���ͨ�����ڴ����ش����µ�
* ��������Ϊ��1���������������������⡣���ǽ��������������������Ϊ
* 18 -- ����1.44MB�����ϻ������������ֵ��
*
* �����ֵ���˲�������⣬����̫С�Ͳ����ˡ�
*
* �μĴ����������óɣ�ds=es=ss=cs - ��ΪINITSEG��0x9000����
* fs = 0��gs = ���������ڶ�ֵ��
*/
85 ! BIOS���õ��ж�0x1E���ж�����ֵ��������������ַ��������ֵλ���ڴ�0x1E * 4 = 0x78
! ������δ������ȴ��ڴ�0x0000:0x0078������ԭ������������0x9000:0xfef4����Ȼ����
! ���е�ÿ�ŵ����������Ϊ18��
86
87 push #0 ! �öμĴ���fs = 0��
88 pop fs ! fs:bxָ�����������������ַ����ָ���ָ�룩��
89 mov bx,#0x78 ! fs:bx is parameter table address
! ����ָ���ʾ��һ�����IJ�������fs�μĴ�����ָ�Ķ��С���ֻӰ������һ����䡣����
! �� fs:bx ��ָ�ڴ�λ�ô��ı���ַ�ŵ��Ĵ����� gs:si ����Ϊԭ��ַ���Ĵ����� es:di =
! 0x9000:0xfef4 ΪĿ�ĵ�ַ��
90 seg fs
91 lgs si,(bx) ! gs:si is source
93 mov di,dx ! es:di is destination ! dx=0xfef4����61�б����á�
94 mov cx,#6 ! copy 12 bytes
95 cld ! �巽���־������ʱָ�������
97 rep ! ����12�ֽڵ�������������0x9000:0xfef4����
98 seg gs
99 movw
100
101 mov di,dx ! es:diָ���±����ı���ƫ��4�������������Ϊ18��
102 movb 4(di),*18 ! patch sector count
103
104 seg fs ! ���ж�����0x1E��ֵָ���±���
105 mov (bx),di
106 seg fs
107 mov 2(bx),es
108
109 pop ax ! ��ʱax���������65�б��������Ķ�ֵ��0x9000����
110 mov fs,ax ! ����fs = gs = 0x9000��
111 mov gs,ax
112
113 xor ah,ah ! reset FDC ! ��λ���̿���������������²�����
114 xor dl,dl ! dl = 0����1��������
115 int 0x13
116
117 ! load the setup-sectors directly after the bootblock.
118 ! Note that 'es' is already set up.
! ��bootsect����������ż���setupģ��Ĵ������ݡ�
! ע��es�Ѿ����ú��ˡ������ƶ�����ʱes�Ѿ�ָ��Ŀ�Ķε�ַ��0x9000����
! 121--137�е���;������ROM BIOS�ж�INT 0x13 ��setup ģ��Ӵ��̵�2��������ʼ����
! 0x90200 ��ʼ�������� 4���������ڶ��������������������������ʾ�����ϳ�������λ�ã�
! Ȼ��λ�����������ԣ�û����·��
! INT 0x13������ʹ�õ��ò����������£�
! ah = 0x02 - �������������ڴ棻al = ��Ҫ����������������
! ch = �ŵ�(����)�ŵĵ�8λ�� cl = ��ʼ����(λ0-5)���ŵ��Ÿ�2λ(λ6-7)��
! dh = ��ͷ�ţ� dl = �������ţ������Ӳ����λ7Ҫ��λ����
! es:bx ��ָ�����ݻ������� ���������CF��־��λ��ah���dz����롣
120 load_setup:
121 xor dx, dx ! drive 0, head 0
122 mov cx,#0x0002 ! sector 2, track 0
123 mov bx,#0x0200 ! address = 512, in INITSEG
124 mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
125 int 0x13 ! read it
126 jnc ok_load_setup ! ok - continue
127
128 push ax ! dump error code ! ��ʾ������Ϣ����������ջ��
129 call print_nl ! ��Ļ���س���
130 mov bp, sp ! ss:bpָ������ʾ���֣�word����
131 call print_hex ! ��ʾʮ������ֵ��
132 pop ax
133
134 xor dl, dl ! reset FDC ! ��λ���̿����������ԡ�
135 xor ah, ah
136 int 0x13
137 j load_setup ! j ��jmpָ�
138
139 ok_load_setup:
140
141 ! Get disk drive parameters, specifically nr of sectors/track
! ��δ���ȡ�����������IJ�����ʵ������ȡÿ�ŵ�����������������λ��sectors����
! ȡ��������������INT 0x13���ø�ʽ�ͷ�����Ϣ���£�
! ah = 0x08 dl = �������ţ������Ӳ����Ҫ��λ7Ϊ1����
! ������Ϣ��
! ���������CF��λ������ah = ״̬�롣
! ah = 0�� al = 0�� bl = ���������ͣ�AT/PS2��
! ch = ���ŵ��ŵĵ�8λ�� cl = ÿ�ŵ����������(λ0-5)�����ŵ��Ÿ�2λ(λ6-7)
! dh = ����ͷ���� dl = ������������
! es:di -�� �������̲�������
142
143 xor dl,dl
144 mov ah,#0x08 ! AH=8 is get drive parameters
145 int 0x13
146 xor ch,ch
! ����ָ���ʾ��һ�����IJ������� cs�μĴ�����ָ�Ķ��С���ֻӰ������һ����䡣ʵ��
! �ϣ����ڱ������������ݶ������ô���ͬһ�����У����μĴ���cs��ds��es��ֵ��ͬ����
! �˱������д˴����Բ�ʹ�ø�ָ�
147 seg cs
! �¾䱣��ÿ�ŵ�������������������˵��dl=0���������ŵ��Ų��ᳬ��256��ch�Ѿ��㹻��
! ʾ�������cl��λ6-7�϶�Ϊ0����146������ch=0����˴�ʱcx����ÿ�ŵ���������
148 mov sectors,cx
149 mov ax,#INITSEG
150 mov es,ax ! ��Ϊ����ȡ���̲����жϸ���esֵ���������¸Ļء�
151
152 ! Print some inane message
! ��ʾ��Ϣ����'Loading'+�س�+���С�������ʾ�����س��ͻ��п����ַ����ڵ�9���ַ���
! BIOS�ж�0x10���ܺ� ah = 0x03�������λ�á�
! ���룺bh = ҳ��
! ���أ�ch = ɨ�迪ʼ�ߣ�cl = ɨ������ߣ�dh = �к�(0x00����)��dl = �к�(0x00�����)��
!
! BIOS�ж�0x10���ܺ� ah = 0x13����ʾ�ַ�����
! ���룺al = ���ù��ķ�ʽ���涨���ԡ�0x01-��ʾʹ��bl�е�����ֵ�����ͣ���ַ�����β����
! es:bp �˼Ĵ�����ָ��Ҫ��ʾ���ַ�����ʼλ�ô���cx = ��ʾ���ַ����ַ�����bh = ��ʾҳ��ţ�
! bl = �ַ����ԡ�dh = �кţ�dl = �кš�
153
154 mov ah,#0x03 ! read cursor pos
155 xor bh,bh ! ���ȶ����λ�á����ع��λ��ֵ��dx�С�
156 int 0x10 ! dh - ��0--24����dl - ��(0--79)��
157
158 mov cx,#9 ! ����ʾ9���ַ���
159 mov bx,#0x0007 ! page 0, attribute 7 (normal)
160 mov bp,#msg1 ! es:bpָ��Ҫ��ʾ���ַ�����
161 mov ax,#0x1301 ! write string, move cursor
162 int 0x10 ! д�ַ������ƶ���굽����β����
163
164 ! ok, we've written the message, now
165 ! we want to load the system (at 0x10000)
! ���ڿ�ʼ��systemģ����ص�0x10000��64KB����ʼ����
166
167 mov ax,#SYSSEG
168 mov es,ax ! segment of 0x010000 ! es = ���system�Ķε�ַ��
169 call read_it ! ��������systemģ�飬esΪ���������
170 call kill_motor ! �ر���������������Ϳ���֪����������״̬�ˡ�
171 call print_nl ! ���س����С�
172
173 ! After that we check which root-device to use. If the device is
174 ! defined (!= 0), nothing is done and the given device is used.
175 ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
176 ! on the number of sectors that the BIOS reports currently.
! �˺����Ǽ��Ҫʹ���ĸ����ļ�ϵͳ�豸����Ƹ��豸��������Ѿ�ָ�����豸(!=0)��
! ��ֱ��ʹ�ø������豸���������Ҫ����BIOS�����ÿ�ŵ���������ȷ������ʹ��/dev/PS0
! (2,28)������ /dev/at0 (2,8)��
!! ����һ���������豸�ļ��ĺ��壺
!! ��Linux�����������豸����2(�μ���43�е�ע��)�����豸�� = type*4 + nr������
!! nrΪ0-3�ֱ��Ӧ����A��B��C��D��type�����������ͣ�2��1.2MB��7��1.44MB�ȣ���
!! ��Ϊ7*4 + 0 = 28������ /dev/PS0 (2,28)ָ����1.44MB A������,���豸����0x021c
!! ͬ�� /dev/at0 (2,8)ָ����1.2MB A�����������豸����0x0208��
! ����root_dev��������������508��509�ֽڴ���ָ���ļ�ϵͳ�����豸�š�0x0306ָ��2
! ��Ӳ�̵�1������������Ĭ��Ϊ0x0306����Ϊ��ʱ Linus ����Linuxϵͳʱ���ڵ�2��Ӳ
! �̵�1�������д�Ÿ��ļ�ϵͳ�����ֵ��Ҫ�������Լ����ļ�ϵͳ����Ӳ�̺ͷ���������
! �ġ����磬�����ĸ��ļ�ϵͳ�ڵ�1��Ӳ�̵ĵ�1�������ϣ���ô��ֵӦ��Ϊ0x0301����
! ��0x01, 0x03����������ļ�ϵͳ���ڵ�2��Bochs�����ϣ���ô��ֵӦ��Ϊ0x021D����
! ��0x1D,0x02�����������ں�ʱ���������Makefile�ļ�������ָ�����Լ���ֵ���ں�ӳ��
! �ļ�Image�Ĵ�������tools/build��ʹ����ָ����ֵ��������ĸ��ļ�ϵͳ�����豸�š�
177
178 seg cs
179 mov ax,root_dev ! ȡ508,509�ֽڴ��ĸ��豸�Ų��ж��Ƿ��ѱ����塣
180 or ax,ax
181 jne root_defined
! ȡ�����148�б����ÿ�ŵ������������sectors=15��˵����1.2MB�������������
! sectors=18����˵����1.44MB��������Ϊ�ǿ������������������Կ϶���A����
182 seg cs
183 mov bx,sectors
184 mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
185 cmp bx,#15 ! �ж�ÿ�ŵ��������Ƿ�=15
186 je root_defined ! ������ڣ���ax�о����������������豸�š�
187 mov ax,#0x021c ! /dev/PS0 - 1.44Mb
188 cmp bx,#18
189 je root_defined
190 undef_root: ! �������һ��������ѭ������������
191 jmp undef_root
192 root_defined:
193 seg cs
194 mov root_dev,ax ! ���������豸�ű��浽root_dev�С�
195
196 ! after that (everyting loaded), we jump to
197 ! the setup-routine loaded directly after
198 ! the bootblock:
! ���ˣ����г�������ϣ����Ǿ���ת����������bootsect�����setup����ȥ��
! ����μ���תָ�Jump Intersegment������ת��0x9020:0000(setup.s����ʼ��)ȥִ�С�
199
200 jmpi 0,SETUPSEG !!!! ���˱�����ͽ����ˡ�!!!!
! �����Ǽ����ӳ���read_it���ڶ�ȡ�����ϵ�systemģ�顣kill_moter���ڹر��������
! ����һЩ��Ļ��ʾ�ӳ���
201
202 ! This routine loads the system at address 0x10000, making sure
203 ! no 64kB boundaries are crossed. We try to load it as fast as
204 ! possible, loading whole tracks whenever we can.
205 !
206 ! in: es - starting address segment (normally 0x1000)
207 !
! ���ӳ���ϵͳģ����ص��ڴ��ַ0x10000������ȷ��û�п�Խ64KB���ڴ�߽硣
! ������ͼ����ؽ��м��أ�ֻҪ���ܣ���ÿ�μ��������ŵ������ݡ�
! ���룺es �C ��ʼ�ڴ��ַ��ֵ��ͨ����0x1000��
!
! ����α������.word����һ��2�ֽ�Ŀ�ꡣ�൱��C���Գ����ж���ı�������ռ�ڴ�ռ��С��
! '1+SETUPLEN'��ʾ��ʼʱ�Ѿ�����1������������setup������ռ��������SETUPLEN��
208 sread: .word 1+SETUPLEN ! sectors read of current track !��ǰ�ŵ����Ѷ���������
209 head: .word 0 ! current head !��ǰ��ͷ�š�
210 track: .word 0 ! current track !��ǰ�ŵ��š�
211
212 read_it:
! ���Ȳ�������Ķ�ֵ�������϶�������ݱ�������λ���ڴ��ַ 64KB �ı߽翪ʼ��������
! ������ѭ������bx�Ĵ��������ڱ�ʾ��ǰ���ڴ�����ݵĿ�ʼλ�á�
! 153���ϵ�ָ��test�Ա���λ������������������������������Ӧ�ı���λ��Ϊ1������
! ֵ�Ķ�Ӧ����λΪ1������Ϊ0���ò������ֻӰ���־�����־ZF�ȣ���������AX=0x1000��
! ��ôtestָ���ִ�н����(0x1000 & 0x0fff) = 0x0000������ZF��־��λ����ʱ����һ��
! ָ��jne ������������
213 mov ax,es
214 test ax,#0x0fff
215 die: jne die ! es must be at 64kB boundary ! esֵ����λ��64KB�߽�!
216 xor bx,bx ! bx is starting address within segment! bxΪ����ƫ�ơ�
217 rp_read:
! �����ж��Ƿ��Ѿ�����ȫ�����ݡ��Ƚϵ�ǰ�������Ƿ����ϵͳ����ĩ�������Ķ�(#ENDSEG)��
! ������Ǿ���ת������ok1_read��Ŵ����������ݡ������˳��ӳ��ء�
218 mov ax,es
219 cmp ax,#ENDSEG ! have we loaded all yet? ! �Ƿ��Ѿ�������ȫ�����ݣ�
220 jb ok1_read
221 ret
222 ok1_read:
! Ȼ��������֤��ǰ�ŵ���Ҫ��ȡ��������������ax�Ĵ����С�
! ���ݵ�ǰ�ŵ���δ��ȡ���������Լ����������ֽڿ�ʼƫ��λ�ã��������ȫ����ȡ��Щδ��
! �������������ֽ����Ƿ�ᳬ��64KB�γ��ȵ����ơ����ᳬ��������ݴ˴�����ܶ�����ֽ�
! �� (64KB �C����ƫ��λ��)��������˴���Ҫ��ȡ����������
223 seg cs
224 mov ax,sectors ! ȡÿ�ŵ���������
225 sub ax,sread ! ��ȥ��ǰ�ŵ��Ѷ���������
226 mov cx,ax ! cx = ax = ��ǰ�ŵ�δ����������
227 shl cx,#9 ! cx = cx * 512 �ֽ� + ���ڵ�ǰƫ��ֵ(bx)��
228 add cx,bx ! = �˴ζ��������ڹ�������ֽ�����
229 jnc ok2_read ! ��û�г���64KB�ֽڣ�����ת��ok2_read��ִ�С�
230 je ok2_read
! �����ϴ˴ν����ŵ�������δ������ʱ�ᳬ��64KB��������ʱ����ܶ�����ֽ�����
! (64KB�C���ڶ�ƫ��λ��)����ת�������ȡ��������������0��ij������ȡ����64KB�IJ�ֵ��
231 xor ax,ax
232 sub ax,bx
233 shr ax,#9
234 ok2_read:
! ����ǰ�ŵ���ָ����ʼ������cl���������������al�������ݵ� es:bx��ʼ����Ȼ��ͳ�Ƶ�ǰ
! �ŵ����Ѿ���ȡ������������ŵ���������� sectors���Ƚϡ����С��sectors˵����ǰ��
! ���ϵĻ�������δ����������ת��ok3_read������������
235 call read_track ! ����ǰ�ŵ���ָ����ʼ��������������������ݡ�
236 mov cx,ax ! cx = �ôβ����Ѷ�ȡ����������
237 add ax,sread ! ���ϵ�ǰ�ŵ����Ѿ���ȡ����������
238 seg cs
239 cmp ax,sectors ! ����ǰ�ŵ��ϵĻ�������δ��������ת��ok3_read����
240 jne ok3_read
! ���ôŵ��ĵ�ǰ��ͷ�����������Ѿ���ȡ������ôŵ�����һ��ͷ�棨1�Ŵ�ͷ���ϵ����ݡ�
! ����Ѿ���ɣ���ȥ����һ�ŵ���
241 mov ax,#1
242 sub ax,head ! �жϵ�ǰ��ͷ�š�
243 jne ok4_read ! �����0��ͷ������ȥ��1��ͷ���ϵ��������ݡ�
244 inc track ! ����ȥ����һ�ŵ���
245 ok4_read:
246 mov head,ax ! ���浱ǰ��ͷ�š�
247 xor ax,ax ! �嵱ǰ�ŵ��Ѷ���������
248 ok3_read:
! �����ǰ�ŵ��ϵĻ���δ�������������ȱ��浱ǰ�ŵ��Ѷ���������Ȼ�����������ݴ��Ŀ�
! ʼλ�á���С��64KB�߽�ֵ������ת��rp_read(217��)�������������ݡ�
249 mov sread,ax ! ���浱ǰ�ŵ��Ѷ���������
250 shl cx,#9 ! �ϴ��Ѷ�������*512�ֽڡ�
251 add bx,cx ! ������ǰ�������ݿ�ʼλ�á�
252 jnc rp_read
! ����˵���Ѿ���ȡ64KB���ݡ���ʱ������ǰ�Σ�Ϊ����һ������������
253 mov ax,es
254 add ah,#0x10 ! ���λ�ַ����Ϊָ����һ��64KB�ڴ濪ʼ����
255 mov es,ax
256 xor bx,bx ! ��������ݿ�ʼƫ��ֵ��
257 jmp rp_read ! ��ת��rp_read(217��)�������������ݡ�
258
! read_track �ӳ�����ǰ�ŵ���ָ����ʼ��������������������ݵ� es:bx ��ʼ�����μ�
! ��67���¶�BIOS���̶��ж�int 0x13��ah=2��˵����
! al �C �����������es:bx �C ��������ʼλ�á�
259 read_track:
! ���ȵ���BIOS�ж�0x10������0x0e���Ե紫��ʽд�ַ��������ǰ��һλ�á���ʾһ��'.'��
260 pusha ! ѹ�����мĴ�����push all����
261 pusha ! Ϊ������ʾ�ж�ѹ�����мĴ���ֵ��
262 mov ax, #0xe2e ! loading... message 2e = .
263 mov bx, #7 ! �ַ�ǰ��ɫ���ԡ�
264 int 0x10
265 popa
! Ȼ����ʽ���дŵ�������������
267 mov dx,track ! ȡ��ǰ�ŵ��š�
268 mov cx,sread ! ȡ��ǰ�ŵ����Ѷ���������
269 inc cx ! cl = ��ʼ��������
270 mov ch,dl ! ch = ��ǰ�ŵ��š�
271 mov dx,head ! ȡ��ǰ��ͷ�š�
272 mov dh,dl ! dh = ��ͷ�ţ�dl = ��������(Ϊ0��ʾ��ǰA������)��
273 and dx,#0x0100 ! ��ͷ�Ų�����1��
274 mov ah,#2 ! ah = 2���������������ܺš�
276 push dx ! save for error dump
277 push cx ! Ϊ�����������һЩ��Ϣ��
278 push bx
279 push ax
281 int 0x13
282 jc bad_rt ! ������������ת��bad_rt��
283 add sp,#8 ! û�г�������˶���Ϊ��������������Ϣ��
284 popa
285 ret
! �����̲���������������ʾ������Ϣ��Ȼ��ִ����������λ�����������жϹ��ܺ�0��������ת
! ��read_track�����ԡ�
287 bad_rt: push ax ! save error code
288 call print_all ! ah = error, al = read
291 xor ah,ah
292 xor dl,dl
293 int 0x13
296 add sp, #10 ! ����Ϊ��������������Ϣ��
297 popa
298 jmp read_track
300 /*
301 * print_all is for debugging purposes.
302 * It will print out all of the registers. The assumption is that this is
303 * called from a routine, with a stack frame like
304 * dx
305 * cx
306 * bx
307 * ax
308 * error
309 * ret <- sp
310 *
311 */
/*
* �ӳ���print_all���ڵ���Ŀ�ġ�������ʾ���мĴ��������ݡ�ǰ����������Ҫ��
* һ���ӳ����е��ã�����ջ֡�ṹΪ������ʾ���������棩
*/
! ����־�Ĵ�����CF=0������ʾ�Ĵ������ơ�
313 print_all:
314 mov cx, #5 ! error code + 4 registers ! ��ʾֵ������
315 mov bp, sp ! ���浱ǰջָ��sp��
317 print_loop:
318 push cx ! save count left ! ������Ҫ��ʾ��ʣ�������
319 call print_nl ! nl for readability ! Ϊ�ɶ������ù��س����С�
320 jae no_reg ! see if register name is needed
321 ! ��FLAGS�ı�־CF=0����ʾ�Ĵ�������������ת��
! ��Ӧ��ջ�Ĵ���˳��ֱ���ʾ���ǵ����ơ�AX�����ȡ�
322 mov ax, #0xe05 + 0x41 - 1 ! ah =���ܺţ�0x0e����al =�ַ���0x05 + 0x41 -1����
323 sub al, cl
324 int 0x10
326 mov al, #0x58 ! X ! ��ʾ�ַ�'X'��
327 int 0x10
329 mov al, #0x3a ! : ! ��ʾ�ַ�':'��
330 int 0x10
! ��ʾ�Ĵ���bp��ָջ�����ݡ���ʼʱbpָ�ص�ַ��
332 no_reg:
333 add bp, #2 ! next register ! ջ����һ��λ�á�
334 call print_hex ! print it ! ��ʮ��������ʾ��
335 pop cx
336 loop print_loop
337 ret
! ����BIOS�ж�0x10���Ե紫��ʽ��ʾ�س����С�
339 print_nl:
340 mov ax, #0xe0d ! CR
341 int 0x10
342 mov al, #0xa ! LF
343 int 0x10
344 ret
346 /*
347 * print_hex is for debugging purposes, and prints the word
348 * pointed to by ss:bp in hexadecmial.
349 */
/*
* �ӳ���print_hex���ڵ���Ŀ�ġ���ʹ��ʮ����������Ļ����ʾ��
* ss:bpָ����֡�
*/
! ����BIOS�ж�0x10���Ե紫��ʽ��4��ʮ����������ʾss:bpָ����֡�
351 print_hex:
352 mov cx, #4 ! 4 hex digits ! Ҫ��ʾ4��ʮ���������֡�
353 mov dx, (bp) ! load word into dx ! ��ʾֵ����dx�С�
354 print_digit:
! ����ʾ���ֽڣ������Ҫ��dx��ֵ����4���أ���ʱ��4������dx�ĵ�4λ�С�
355 rol dx, #4 ! rotate so that lowest 4 bits are used
356 mov ah, #0xe ! �жϹ��ܺš�
357 mov al, dl ! mask off so we have only next nibble
358 and al, #0xf ! ����al�в�ֻȡ��4���أ�1��ֵ����
! ����'0' ��ASCII��ֵ0x30������ʾֵת���ɻ�������'0' ���ַ�������ʱal ֵ���� 0x39��
! ��ʾ����ʾֵ��������9�������Ҫʹ��'A'--'F'����ʾ��
359 add al, #0x30 ! convert to 0 based digit, '0'
360 cmp al, #0x39 ! check for overflow
361 jbe good_digit
362 add al, #0x41 - 0x30 - 0xa ! 'A' - '0' - 0xa
364 good_digit:
365 int 0x10
366 loop print_digit ! cx--����cx>0��ȥ��ʾ��һ��ֵ��
367 ret
370 /*
371 * This procedure turns off the floppy drive motor, so
372 * that we enter the kernel in a known state, and
373 * don't have to worry about it later.
374 */
/* ����ӳ������ڹر�����������������ǽ����ں˺����
* ֪����������״̬���Ժ�Ҳ�����뵣�����ˡ�
*/
! �����377���ϵ�ֵ0x3f2�����̿�������һ���˿ڣ�����Ϊ��������Ĵ�����DOR���˿ڡ�����
! һ��8λ�ļĴ�������λ7--λ4�ֱ����ڿ���4��������D--A���������رա�λ3--λ2����
! ����/��ֹDMA���ж������Լ�����/��λ���̿�����FDC�� λ1--λ0����ѡ��ѡ�������������
! ��378������al�����ò������0ֵ����������ѡ��A���������ر�FDC����ֹDMA���ж�����
! �ر�����й��������ƿ���̵���ϸ��Ϣ��μ�kernel/blk_drv/floppy.c��������˵����
375 kill_motor:
376 push dx
377 mov dx,#0x3f2 ! �������ƿ�����������Ĵ����˿ڣ�ֻд��
378 xor al, al ! A���������ر�FDC����ֹDMA���ж����ر����
379 outb ! ��al�е����������dxָ���Ķ˿�ȥ��
380 pop dx
381 ret
383 sectors:
384 .word 0 ! ��ŵ�ǰ��������ÿ�ŵ�����������
386 msg1: ! ��������BIOS�ж���ʾ����Ϣ����9���ַ���
387 .byte 13,10 ! �س������е�ASCII�롣
388 .ascii "Loading"
! ��ʾ�������ӵ�ַ508(0x1FC)��ʼ������root_dev�����������ĵ�508��ʼ��2���ֽ��С�
390 .org 506
391 swap_dev:
392 .word SWAP_DEV ! �����Ž���ϵͳ�����豸��(init/main.c�л���)��
393 root_dev:
394 .word ROOT_DEV ! �����Ÿ��ļ�ϵͳ�����豸��(init/main.c�л���)��
! �����������̾�����Ч���������ı�־������BIOS�еij��������������ʱʶ��ʹ�á�������
! λ��������������������ֽ��С�
395 boot_flag:
396 .word 0xAA55
398 .text
399 endtext:
400 .data
401 enddata:
402 .bss
403 endbss:
1 !
2 ! setup.s (C) 1991 Linus Torvalds
3 !
4 ! setup.s is responsible for getting the system data from the BIOS,
5 ! and putting them into the appropriate places in system memory.
6 ! both setup.s and system has been loaded by the bootblock.
7 !
8 ! This code asks the bios for memory/disk/other parameters, and
9 ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
10 ! boot-block used to be. It is then up to the protected mode
11 ! system to read them from there before the area is overwritten
12 ! for buffer-blocks.
13 !
! setup.s�����BIOS�л�ȡϵͳ���ݣ�������Щ���ݷŵ�ϵͳ�ڴ���ʵ�
! �ط�����ʱsetup.s��system�Ѿ���bootsect��������ص��ڴ��С�
!
! ��δ���ѯ��bios�й��ڴ�/����/����������������Щ�����ŵ�һ��
! ����ȫ�ġ��ط���0x90000-0x901FF��Ҳ��ԭ��bootsect�����������
! �ĵط���Ȼ���ڱ�����鸲�ǵ�֮ǰ�ɱ���ģʽ��system��ȡ��
15 ! NOTE! These had better be the same as in bootsect.s!
! ������Щ������ú�bootsect.s�е���ͬ��
16 #include <linux/config.h>
! config.h�����DEF_INITSEG = 0x9000��DEF_SYSSEG = 0x1000��DEF_SETUPSEG = 0x9020��
18 INITSEG = DEF_INITSEG ! we move boot here - out of the way ! ԭ��bootsect�����ĶΡ�
19 SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). ! system��0x10000����
20 SETUPSEG = DEF_SETUPSEG ! this is the current segment ! ���������ڵĶε�ַ��
22 .globl begtext, begdata, begbss, endtext, enddata, endbss
23 .text
24 begtext:
25 .data
26 begdata:
27 .bss
28 begbss:
29 .text
31 entry start
32 start:
34 ! ok, the read went well so we get current cursor position and save it for
35 ! posterity.
! ok�����������̹��̶����������ڽ����λ�ñ����Ա����ʹ�ã���ش�����59--62�У���
! �¾佫ds�ó�INITSEG(0x9000)�����Ѿ���bootsect���������ù�������������setup����
! Linus������Ҫ����������һ�¡�
37 mov ax,#INITSEG
38 mov ds,ax
40 ! Get memory size (extended mem, kB)
! ȡ��չ�ڴ�Ĵ�Сֵ��KB����
! ����BIOS�ж�0x15 ���ܺ�ah = 0x88 ȡϵͳ������չ�ڴ��С���������ڴ�0x90002����
! ���أ�ax = ��0x100000��1M������ʼ����չ�ڴ��С(KB)����������CF��λ��ax = �����롣
42 mov ah,#0x88
43 int 0x15
44 mov [2],ax ! ����չ�ڴ���ֵ����0x90002����1���֣���
46 ! check for EGA/VGA and some config parameters
! �����ʾ��ʽ��EGA/VGA����ȡ������
! ����BIOS�ж�0x10�����ӹ���ѡ��ʽ��Ϣ�����ܺţ�ah = 0x12��bl = 0x10
! ���أ�bh =��ʾ״̬��0x00 -��ɫģʽ��I/O�˿�=0x3dX��0x01 -��ɫģʽ��I/O�˿�=0x3bX��
! bl = ��װ����ʾ�ڴ档0x00 - 64k��0x01 - 128k��0x02 - 192k��0x03 = 256k��
! cx = ��ʾ�����Բ���(�μ�������BIOS��Ƶ�ж�0x10��˵��)��
48 mov ah,#0x12
49 mov bl,#0x10
50 int 0x10
51 mov [8],ax ! 0x90008 = ??
52 mov [10],bx ! 0x9000A =��װ����ʾ�ڴ棻0x9000B=��ʾ״̬(��/��ɫ)
53 mov [12],cx ! 0x9000C =��ʾ�����Բ�����
! �����Ļ��ǰ����ֵ������ʾ����VGA��ʱ�������û�ѡ����ʾ����ֵ�������浽0x9000E����
54 mov ax,#0x5019 ! ��ax��Ԥ����ĻĬ������ֵ��ah = 80�У�al=25�У���
55 cmp bl,#0x10 ! ���жϷ���blֵΪ0x10�����ʾ����VGA��ʾ������ת��
56 je novga
57 call chsvga ! �����ʾ�����Һ����ͣ�����ʾ����ֵ����215�У���
58 novga: mov [14],ax ! ������Ļ��ǰ����ֵ��0x9000E��0x9000F����
! ��δ���ʹ��BIOS�ж�ȡ��Ļ��ǰ���λ�ã��С��У������������ڴ�0x90000����2�ֽڣ���
! ����̨��ʼ������ᵽ�˴���ȡ��ֵ��
! BIOS�ж�0x10���ܺ� ah = 0x03�������λ�á�
! ���룺bh = ҳ��
! ���أ�ch = ɨ�迪ʼ�ߣ�cl = ɨ������ߣ�dh = �к�(0x00����)��dl = �к�(0x00�����)��
59 mov ah,#0x03 ! read cursor pos
60 xor bh,bh
61 int 0x10 ! save it in known place, con_init fetches
62 mov [0],dx ! it from 0x90000.
64 ! Get video-card data:
! �����������ȡ��ʾ����ǰ��ʾģʽ��
! ����BIOS�ж�0x10�����ܺ� ah = 0x0f
! ���أ�ah = �ַ�������al = ��ʾģʽ��bh = ��ǰ��ʾҳ��
! 0x90004(1��)��ŵ�ǰҳ��0x90006�����ʾģʽ��0x90007����ַ�������
66 mov ah,#0x0f
67 int 0x10
68 mov [4],bx ! bh = display page
69 mov [6],ax ! al = video mode, ah = window width
71 ! Get hd0 data
! ȡ��һ��Ӳ�̵���Ϣ������Ӳ�̲���������
! ��1��Ӳ�̲���������ַ��Ȼ���ж�����0x41������ֵ������2��Ӳ�̲����������ڵ�1��
! ���ĺ��棬�ж�����0x46������ֵҲָ���2��Ӳ�̵IJ�������ַ�����ij�����16���ֽڡ�
! �������γ���ֱ���ROM BIOS���й�����Ӳ�̵IJ�������0x90080����ŵ�1��Ӳ�̵ı���
! 0x90090����ŵ�2��Ӳ�̵ı���
! ��75�������ڴ�ָ��λ�ô���ȡһ����ָ��ֵ������ds��si�Ĵ����С�ds�зŶε�ַ��
! si�Ƕ���ƫ�Ƶ�ַ�������ǰ��ڴ��ַ4 * 0x41��= 0x104���������4���ֽڶ�������4��
! �ڼ���Ӳ�̲���������λ�õĶκ�ƫ��ֵ��
73 mov ax,#0x0000
74 mov ds,ax
75 lds si,[4*0x41] ! ȡ�ж�����0x41��ֵ����hd0�������ĵ�ַ��ds:si
76 mov ax,#INITSEG
77 mov es,ax
78 mov di,#0x0080 ! �����Ŀ�ĵ�ַ: 0x9000:0x0080 �� es:di
79 mov cx,#0x10 ! ������16�ֽڡ�
80 rep
81 movsb
83 ! Get hd1 data
85 mov ax,#0x0000
86 mov ds,ax
87 lds si,[4*0x46] ! ȡ�ж�����0x46��ֵ����hd1�������ĵ�ַ��ds:si
88 mov ax,#INITSEG
89 mov es,ax
90 mov di,#0x0090 ! �����Ŀ�ĵ�ַ: 0x9000:0x0090 �� es:di
91 mov cx,#0x10
92 rep
93 movsb
95 ! Check that there IS a hd1 :-)
! ���ϵͳ�Ƿ��е�2��Ӳ�̡����û����ѵ�2�������㡣
! ����BIOS�жϵ���0x13��ȡ�������ܣ����ܺ� ah = 0x15��
! ���룺dl = �������ţ�0x8X��Ӳ�̣�0x80ָ��1��Ӳ�̣�0x81��2��Ӳ�̣�
! �����ah = �����룻00 - û������̣�CF��λ��01 - ��������û��change-line֧�֣�
! 02 - ������(���������ƶ��豸)����change-line֧�֣� 03 - ��Ӳ�̡�
97 mov ax,#0x01500
98 mov dl,#0x81
99 int 0x13
100 jc no_disk1
101 cmp ah,#3 ! ��Ӳ����(���� = 3 ��)��
102 je is_disk1
103 no_disk1:
104 mov ax,#INITSEG ! ��2��Ӳ�̲����ڣ���Ե�2��Ӳ�̱����㡣
105 mov es,ax
106 mov di,#0x0090
107 mov cx,#0x10
108 mov ax,#0x00
109 rep
110 stosb
111 is_disk1:
113 ! now we want to move to protected mode ...
! ��������Ҫ���뱣��ģʽ����...
115 cli ! no interrupts allowed ! ! �Ӵ˿�ʼ�������жϡ�
117 ! first we move the system to it's rightful place
! �������ǽ�systemģ���Ƶ���ȷ��λ�á�
! bootsect���������� system ģ����뵽�ڴ� 0x10000��64KB����ʼ��λ�á����ڵ�ʱ����
! systemģ����Ȳ��ᳬ��0x80000��512KB��������ĩ�˲��ᳬ���ڴ��ַ0x90000������
! bootsect����Լ��ƶ���0x90000��ʼ�ĵط�������setup���ص����ĺ��档������γ����
! ��;���ٰ�����systemģ���ƶ��� 0x00000λ�ã����Ѵ� 0x10000��0x8ffff ���ڴ����ݿ�
! ��512KB����������ڴ�Ͷ��ƶ���0x10000��64KB����λ�á�
119 mov ax,#0x0000
120 cld ! 'direction'=0, movs moves forward
121 do_move:
122 mov es,ax ! destination segment ! es:di��Ŀ�ĵ�ַ(��ʼΪ0x0:0x0)
123 add ax,#0x1000
124 cmp ax,#0x9000 ! �Ѿ������һ�Σ���0x8000�ο�ʼ��64KB�������ƶ��ꣿ
125 jz end_move ! �ǣ�����ת��
126 mov ds,ax ! source segment ! ds:si��Դ��ַ(��ʼΪ0x1000:0x0)
127 sub di,di
128 sub si,si
129 mov cx,#0x8000 ! �ƶ�0x8000�֣�64KB�ֽڣ���
130 rep
131 movsw
132 jmp do_move
134 ! then we load the segment descriptors
! �˺����Ǽ��ض���������
! �����↑ʼ������32λ����ģʽ�IJ����������ҪIntel 32λ����ģʽ��̷����֪ʶ�ˣ�
! �й��ⷽ�����Ϣ������б���ļ��ܻ�¼�е���ϸ˵�������������Ҫ˵�����ڽ���
! ����ģʽ������֮ǰ��������Ҫ�������ú���Ҫʹ�õĶ�����������������Ҫ����ȫ��������
! ���������������
!
! ����ָ��lidt���ڼ����ж�����������IDT���Ĵ��������IJ�������idt_48����6�ֽڡ�ǰ2
! �ֽڣ��ֽ�0-1���������������ֽڳ���ֵ����4�ֽڣ��ֽ�2-5��������������32λ���Ի�
! ��ַ������ʽ�μ�����218--220�к�222--224��˵�����ж����������е�ÿһ��8�ֽڱ���
! ָ�������ж�ʱ��Ҫ���õĴ�����Ϣ�����ж�������Щ���ƣ���Ҫ�����������Ϣ��
!
! lgdtָ�����ڼ���ȫ������������GDT���Ĵ��������������ʽ��lidtָ�����ͬ��ȫ������
! �����е�ÿ���������8�ֽڣ������˱���ģʽ�����ݶκʹ���Σ��飩����Ϣ�� ���а���
! �ε�������ƣ�16λ�����ε����Ե�ַ��ַ��32λ�����ε���Ȩ�������Ƿ����ڴ桢��д
! ����Ȩ�Լ�����һЩ����ģʽ���еı�־���μ�����205--216�С�
136 end_move:
137 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)
138 mov ds,ax ! dsָ����(setup)�Ρ�
139 lidt idt_48 ! load idt with 0,0 ! ����IDT�Ĵ�����
140 lgdt gdt_48 ! load gdt with whatever appropriate ! ����GDT�Ĵ�����
142 ! that was painless, now we enable A20
! ���ϵIJ����ܼ��������ǿ���A20��ַ�ߡ�
! Ϊ���ܹ����ʺ�ʹ��1MB���ϵ������ڴ棬������Ҫ���ȿ���A20��ַ�ߡ��μ��������б���
! �й�A20�ź��ߵ�˵�����������漰��һЩ�˿ں�����ɲο�kernel/chr_drv/keyboard.S
! �����Լ��̽ӿڵ�˵�������ڻ����Ƿ�����������A20��ַ�ߣ����ǻ���Ҫ�ڽ��뱣��ģʽ
! ֮���ܷ���1MB�����ڴ�֮���ڲ���һ�¡��������������head.S�����У�32--36�У���
144 call empty_8042 ! ����8042״̬�Ĵ������ȴ����뻺�����ա�
! ֻ�е����뻺����Ϊ��ʱ�ſ��Զ���ִ��д���
145 mov al,#0xD1 ! command write ! 0xD1������-��ʾҪд���ݵ�
146 out #0x64,al ! 8042��P2�˿ڡ�P2�˿�λ1����A20�ߵ�ѡͨ��
147 call empty_8042 ! �ȴ����뻺�����գ��������Ƿ��ܡ�
148 mov al,#0xDF ! A20 on ! ѡͨA20��ַ�ߵIJ�����
149 out #0x60,al ! ����Ҫд��0x60�ڡ�
150 call empty_8042 ! ����ʱ���뻺����Ϊ�գ����ʾA20���Ѿ�ѡͨ��
152 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
153 ! we put them right after the intel-reserved hardware interrupts, at
154 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
155 ! messed this up with the original PC, and they haven't been able to
156 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
157 ! which is used for the internal hardware interrupts as well. We just
158 ! have to reprogram the 8259's, and it isn't fun.
!
! ϣ������һ���������������DZ������¶��жϽ��б�� :-( ���ǽ����Ƿ�������
! ����Intel������Ӳ���жϺ��棬��int 0x20--0x2F�����������Dz��������ͻ��
! ���ҵ���IBM��ԭPC���и����ˣ��Ժ�Ҳû�о�������������PC��BIOS���ж�
! ������0x08--0x0f����Щ�ж�Ҳ�������ڲ�Ӳ���жϡ��������Ǿͱ������¶�8259
! �жϿ��������б�̣���һ�㶼û��˼��
!
! PC��ʹ��2��8259AоƬ�����ڶԿɱ�̿�����8259AоƬ�ı�̷�����μ��������Ľ��ܡ�
! ��162���϶���������֣�0x00eb����ֱ��ʹ�û������ʾ�����������תָ�����ʱ���á�
! 0xeb��ֱ�ӽ���תָ��IJ����룬��1���ֽڵ����λ��ֵ�������ת��Χ��-127��127��CPU
! ͨ����������λ��ֵ�ӵ�EIP�Ĵ����о��γ�һ���µ���Ч��ַ����ʱEIPָ����һ����ִ��
! ��ָ�ִ��ʱ�����ѵ�CPUʱ����������7��10����0x00eb ��ʾ��תֵ��0��һ��ָ���
! �˻���ֱ��ִ����һ��ָ�������ָ����ṩ14--20��CPUʱ�����ڵ��ӳ�ʱ�䡣��as86
! ��û�б�ʾ��Ӧָ������Ƿ������Linus��setup.s��һЩ�������о�ֱ��ʹ�û���������
! ʾ����ָ����⣬ÿ���ղ���ָ��NOP��ʱ����������3���������Ҫ�ﵽ��ͬ���ӳ�Ч����
! ��Ҫ6��7��NOPָ�
! 8259оƬ��Ƭ�˿���0x20-0x21����Ƭ�˿���0xA0-0xA1�����ֵ0x11��ʾ��ʼ�����ʼ��
! ����ICW1�����֣���ʾ���ش�������Ƭ8259���������Ҫ����ICW4�����֡�
160 mov al,#0x11 ! initialization sequence
161 out #0x20,al ! send it to 8259A-1 ! ���͵�8259A��оƬ��
162 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2 ! '$'��ʾ��ǰָ��ĵ�ַ��
163 out #0xA0,al ! and to 8259A-2 ! �ٷ��͵�8259A��оƬ��
164 .word 0x00eb,0x00eb
! LinuxϵͳӲ���жϺű����óɴ�0x20��ʼ���μ���3-2��Ӳ���ж������ź����жϺŶ�Ӧ����
165 mov al,#0x20 ! start of hardware int's (0x20)
166 out #0x21,al ! ����оƬICW2�����֣�������ʼ�жϺţ�Ҫ����˿ڡ�
167 .word 0x00eb,0x00eb
168 mov al,#0x28 ! start of hardware int's 2 (0x28)
169 out #0xA1,al ! �ʹ�оƬICW2�����֣���оƬ����ʼ�жϺš�
170 .word 0x00eb,0x00eb
171 mov al,#0x04 ! 8259-1 is master
172 out #0x21,al ! ����оƬICW3�����֣���оƬ��IR2����оƬINT��
���μ������б����˵����
173 .word 0x00eb,0x00eb
174 mov al,#0x02 ! 8259-2 is slave
175 out #0xA1,al ! �ʹ�оƬICW3�����֣���ʾ��оƬ��INT������о
! Ƭ��IR2�����ϡ�
176 .word 0x00eb,0x00eb
177 mov al,#0x01 ! 8086 mode for both
178 out #0x21,al ! ����оƬICW4�����֡�8086ģʽ����ͨEOI���ǻ���
! ��ʽ���跢��ָ������λ����ʼ��������оƬ������
179 .word 0x00eb,0x00eb
180 out #0xA1,al ���ʹ�оƬICW4�����֣�����ͬ�ϡ�
181 .word 0x00eb,0x00eb
182 mov al,#0xFF ! mask off all interrupts for now
183 out #0x21,al ! ������оƬ�����ж�����
184 .word 0x00eb,0x00eb
185 out #0xA1,al �����δ�оƬ�����ж�����
187 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
188 ! need no steenking BIOS anyway (except for the initial loading :-).
189 ! The BIOS-routine wants lots of unnecessary data, and it's less
190 ! "interesting" anyway. This is how REAL programmers do it.
191 !
192 ! Well, now's the time to actually move into protected mode. To make
193 ! things as simple as possible, we do no register set-up or anything,
194 ! we let the gnu-compiled 32-bit programs do that. We just jump to
195 ! absolute address 0x00000, in 32-bit protected mode.
!
! �ߣ�������α�̵�Ȼû��:-(����ϣ�������ܹ�������������Ҳ������Ҫ��ζ��BIOS
! �ˣ����˳�ʼ����:-)��BIOS�ӳ���Ҫ��ܶ��Ҫ�����ݣ�������һ�㶼ûȤ������
! ���������ij���Ա�������¡�
!
! ���ˣ�������������ʼ���뱣��ģʽ��ʱ���ˡ�Ϊ�˰��������þ��������Dz�����
! �Ĵ������ݽ����κ����á�������gnu�����32λ����ȥ������Щ�¡��ڽ���32λ��
! ��ģʽʱ���ǽ��Ǽ���ת�����Ե�ַ0x00000����
! �������ò�����32λ����ģʽ���С����ȼ��ػ���״̬��(lmsw-Load Machine Status Word)��
! Ҳ�ƿ��ƼĴ���CR0�������λ0��1������CPU�л�������ģʽ��������������Ȩ��0�У���
! ��ǰ��Ȩ��CPL=0����ʱ�μĴ�����Ȼָ����ʵ��ַģʽ����ͬ�����Ե�ַ������ʵ��ַģʽ��
! ���Ե�ַ�������ڴ��ַ��ͬ���������øñ���λ�����һ��ָ�������һ���μ���תָ����
! ����ˢ��CPU��ǰָ����С���ΪCPU����ִ��һ��ָ��֮ǰ���Ѵ��ڴ��ȡ��ָ��������
! ���롣Ȼ���ڽ��뱣��ģʽ�Ժ���Щ����ʵģʽ��Ԥ��ȡ�õ�ָ����Ϣ�ͱ�ò�����Ч����һ��
! �μ���תָ��ͻ�ˢ��CPU�ĵ�ǰָ����У���������Щ��Ч��Ϣ�����⣬��Intel��˾���ֲ�
! �Ͻ���80386������CPUӦ��ʹ��ָ����mov cr0,ax���л�������ģʽ��lmswָ������ڼ�����
! ǰ��286 CPU��
197 mov ax,#0x0001 ! protected mode (PE) bit ! ����ģʽ����λ(PE)��
198 lmsw ax ! This is it! ! ���������ػ���״̬��!
199 jmpi 0,8 ! jmp offset 0 of segment 8 (cs) ! ��ת��cs��ƫ��0����
! �����Ѿ���systemģ���ƶ���0x00000��ʼ�ĵط��������Ͼ��е�ƫ�Ƶ�ַ��0������ֵ8�Ѿ�
! �DZ���ģʽ�µĶ�ѡ����ˣ�����ѡ�����������������������Լ���Ҫ�����Ȩ������ѡ�����
! ��Ϊ16λ��2�ֽڣ���λ0-1��ʾ�������Ȩ��0--3����Linux����ϵͳֻ�õ�������0������
! �˼�����3�����û�������λ2����ѡ��ȫ������������0�����Ǿֲ���������(1)��λ3-15����
! ���������������ָ��ѡ��ڼ��������������Զ�ѡ���8��0b0000,0000,0000,1000����ʾ����
! ��Ȩ��0��ʹ��ȫ����������GDT�е�2���������������ָ������Ļ���ַ��0���μ�571�У���
! ����������תָ��ͻ�ȥִ��system�еĴ��롣���⣬
201 ! This routine checks that the keyboard command queue is empty
202 ! No timeout is used - if this hangs there is something wrong with
203 ! the machine, and we probably couldn't proceed anyway.
! ��������ӳ����������������Ƿ�Ϊ�ա����ﲻʹ�ó�ʱ���� -
! ���������������˵��PC�������⣬���Ǿ�û�а취�ٴ�����ȥ�ˡ�
!
! ֻ�е����뻺����Ϊ��ʱ�����̿�����״̬�Ĵ���λ1 = 0���ſ��Զ���ִ��д���
204 empty_8042:
205 .word 0x00eb,0x00eb
206 in al,#0x64 ! 8042 status port ! ��AT���̿�����״̬�Ĵ�����
207 test al,#2 ! is input buffer full? ! ����λ1�����뻺��������
208 jnz empty_8042 ! yes - loop
209 ret
211 ! Routine trying to recognize type of SVGA-board present (if any)
212 ! and if it recognize one gives the choices of resolution it offers.
213 ! If one is found the resolution chosen is given by al,ah (rows,cols).
! ����������ʶ��SVGA��ʾ�������еĻ������ӳ�����ʶ���һ������û�
! �ṩѡ��ֱ��ʵĻ��ᣬ���ѷֱ��ʷ���Ĵ���al��ah���С��У��з��ء�
!
! ע������215--566�д���ǣ�浽�ڶ���ʾ���˿���Ϣ����˱Ƚϸ��ӡ���������δ������ں�
! ���й�ϵ������˿�������������
! ����������ʾ588���ϵ�msg1�ַ�����"��<�س���>�鿴���ڵ�SVGAģʽ�������������"����
! Ȼ��ѭ����ȡ���̿�����������������ȴ��û�����������û����»س�����ȥ���ϵͳ����
! ��SVGAģʽ������AL��AH�з����������ֵ����������Ĭ��ֵAL=25�С�AH=80�в����ء�
215 chsvga: cld
216 push ds ! ����dsֵ������231�У���490��492�У�������
217 push cs ! ��Ĭ�����ݶ����óɺʹ����ͬһ���Ρ�
218 pop ds
219 mov ax,#0xc000
220 mov es,ax ! es ָ��0xc000�Ρ��˴���VGA���ϵ�ROM BIOS����
221 lea si,msg1 ! ds:siָ��msg1�ַ�����
222 call prtstr ! ��ʾ��NULL��β��msg1�ַ�����
223 nokey: in al,#0x60 ! ��ȡ���̿�������������������Լ��̵�ɨ����������
224 cmp al,#0x82 ! ����յ���0x82С��ɨ�������ǽ�ͨɨ���룬��Ϊ0x82��
225 jb nokey ! ��С�Ͽ�ɨ����ֵ��С��0x82��ʾ��û�а����ɿ���
226 cmp al,#0xe0 ! ���ɨ�������0xe0����ʾ�յ�������չɨ����ǰ��
227 ja nokey
228 cmp al,#0x9c ! ����Ͽ�ɨ������0x9c����ʾ�û�����/�ɿ��˻س�����
229 je svga ! ���dz�����תȥ���ϵͳ�Ƿ����SVGAģʽ��
230 mov ax,#0x5019 ! �����AX�з�������ֵĬ������ΪAL=25�С�AH=80�С�
231 pop ds
232 ret
! �������VGA��ʾ���ϵ�ROM BIOSָ��λ�ô����������ݴ�����֧�ֵ��ر������жϻ�����
! ��װ����ʲô���ӵ���ʾ����������֧��10����ʾ������չ���ܡ�ע�⣬��ʱ�����Ѿ��ڵ�
! 220�а�esָ��VGA����ROM BIOS���ڵĶ�0xc000���μ���2�£���
! �����ж��Dz���ATI��ʾ�������ǰ� ds:siָ��595����ATI��ʾ���������ݴ�������es:siָ
! ��VGA BIOS��ָ��λ�ã�ƫ��0x31��������Ϊ������������9���ַ���"761295520"���������
! ��ѭ���Ƚ�����������������ͬ���ʾ�����е�VGA����ATI���ӵģ�������ds:siָ�����
! ʾ���������õ�����ģʽֵdscati����615�У�����diָ��ATI�������õ����и�����ģʽ��
! ����ת�����selmod��438�У�����һ���������á�
233 svga: lea si,idati ! Check ATI 'clues' ! ����ж� ATI��ʾ�������ݡ�
234 mov di,#0x31 ! ��������0xc000:0x0031��ʼ��
235 mov cx,#0x09 ! ��������9���ֽڡ�
236 repe
237 cmpsb
238 jne noati ! ����������ͬ���ʾ����ATI��ʾ������ת��������
239 lea si,dscati ! ���9���ֽڶ���ͬ����ʾϵͳ����һ��ATI����ʾ����
240 lea di,moati ! ����siָ��ATI�����еĿ�ѡ����ֵ��diָ���ѡ����
241 lea cx,selmod ! ��ģʽ�б���Ȼ����ת��selmod��438�У�������������
242 jmp cx
! �������ж��Dz���Ahead���ӵ���ʾ����������EGA/VGA ͼ�������Ĵ���0x3ceд������ʵ�
! �������Ĵ���������0x0f��ͬʱ��0x3cf�˿ڣ���ʱ��Ӧ�������Ĵ�����д�뿪����չ�Ĵ���
! ��־ֵ0x20��Ȼ��ͨ��0x3cf�˿ڶ�ȡ�������Ĵ���ֵ���Լ���Ƿ�������ÿ�����չ�Ĵ���
! ��־�����������˵����Ahead���ӵ���ʾ����ע��word���ʱal���˿�n��ah���˿�n+1��
243 noati: mov ax,#0x200f ! Check Ahead 'clues'
244 mov dx,#0x3ce ! ���ݶ˿�ָ���������Ĵ�����0x0f��0x3ce�˿ڣ���
245 out dx,ax ! �����ÿ�����չ�Ĵ�����־��0x20��0x3cf�˿ڣ���
246 inc dx ! Ȼ���ٶ�ȡ�üĴ��������ñ�־�Ƿ������ϡ�
247 in al,dx
248 cmp al,#0x20 ! �����ȡֵ��0x20�����ʾ��Ahead A��ʾ����
249 je isahed ! �����ȡֵ��0x21�����ʾ��Ahead B��ʾ����
250 cmp al,#0x21 ! ����˵������Ahead��ʾ����������ת������������
251 jne noahed
252 isahed: lea si,dscahead ! si ָ��Ahead��ʾ����ѡ����ֵ����diָ����չģʽ��
253 lea di,moahead ! ������չģʽ���б���Ȼ����ת��selmod��438�У�����
254 lea cx,selmod ! ��������
255 jmp cx
! ����������Dz���Chips & Tech��������ʾ����ͨ���˿�0x3c3��0x94��0x46e8������VGA����
! �Ĵ����Ľ�������ģʽ��־��λ4����Ȼ��Ӷ˿�0x104��ȡ��ʾ��оƬ����ʶֵ������ñ�ʶֵ
! ��0xA5����˵����Chips & Tech��������ʾ����
256 noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues'
257 in al,dx ! ��0x3c3�˿ڶ�ȡVGA�����Ĵ���ֵ�������Ͻ�������ģʽ
258 or al,#0x10 ! ��־��λ4������д�ء�
259 out dx,al
260 mov dx,#0x104 ! ������ģʽʱ��ȫ�ֱ�ʶ�˿�0x104��ȡ��ʾ��оƬ��ʶֵ��
261 in al,dx ! ����ʱ�����bl�Ĵ����С�
262 mov bl,al
263 mov dx,#0x3c3 ! Ȼ���0x3c3�˿��еĽ�������ģʽ��־��λ��
264 in al,dx
265 and al,#0xef
266 out dx,al
267 cmp bl,[idcandt] ! �ٰ�bl�б�ʶֵ��λ��idcandt������596�У���Chips &
268 jne nocant ! Tech�ı�ʶֵ0xA5���Ƚϡ������ͬ����ת�Ƚ���һ���Կ���
269 lea si,dsccandt ! ��siָ��������ʾ���Ŀ�ѡ����ֵ����diָ����չģʽ����
270 lea di,mocandt ! ����չģʽ���б���Ȼ����ת��selmod��438�У���������
271 lea cx,selmod ! ��ʾģʽ�IJ�����
272 jmp cx
! ���ڼ���Dz���Cirrus��ʾ����������ʹ��CRT������������0x1f�Ĵ��������������Խ�ֹ��չ
! ���ܡ��üĴ�������Ϊӥ�꣨Eagle ID���Ĵ���������ֵ�ߵͰ��ֽڽ���һ�º�д��˿�0x3c4��
! ����6�ţ�����/��չ���Ĵ���Ӧ�û��ֹCirrus��ʾ������չ���ܡ����������˵������Cirrus
! ��ʾ������Ϊ�Ӷ˿�0x3d4������0x1fӥ��Ĵ����ж�ȡ��������ӥ��ֵ��0x0c�����Ŷ�Ӧ����
! ����ʼ��ַ���ֽڼĴ�������������֮���ֵ������ڶ�0x1f������֮ǰ������Ҫ�Ȱ��Դ���ʼ
! ���ֽڼĴ������ݱ�������㣬���ڼ���ָ�֮�����⣬��û�н�������Eagle IDֵд��0x3c4
! �˿�������6�Ŷ���/��չ�Ĵ��������¿�����չ���ܡ�
273 nocant: mov dx,#0x3d4 ! Check Cirrus 'clues'
274 mov al,#0x0c ! ������CRT���ƼĴ����������Ĵ����˿�0x3d4д��Ҫ����
275 out dx,al ! �ļĴ���������0x0c����Ӧ�Դ���ʼ��ַ���ֽڼĴ�������
276 inc dx ! Ȼ���0x3d5�˿ڶ����Դ���ʼ��ַ���ֽڲ��ݴ���bl�У�
277 in al,dx ! �ٰ��Դ���ʼ��ַ���ֽڼĴ������㡣
278 mov bl,al
279 xor al,al
280 out dx,al
281 dec dx ! ������0x3d4�˿��������0x1f��ָ������Ҫ��0x3d5�˿�
282 mov al,#0x1f ! ���ʶ�ȡ��Eagle ID���Ĵ������ݡ�
283 out dx,al
284 inc dx
285 in al,dx ! ��0x3d5�˿ڶ�ȡ��Eagle ID���Ĵ���ֵ�����ݴ���bh�С�
286 mov bh,al ! Ȼ��Ѹ�ֵ�ߵ�4���ػ���λ�ô�ŵ�cl�С�������8λ
287 xor ah,ah ! �����ch�У���cl�з�����ֵ6��
288 shl al,#4
289 mov cx,ax
290 mov al,bh
291 shr al,#4
292 add cx,ax
293 shl cx,#8
294 add cx,#6 ! ����cxֵ�����ax�С���ʱah���ǻ�λ��ġ�Eagle
295 mov ax,cx ! ID��ֵ��al����������6����Ӧ����/��չ�Ĵ�������ah
296 mov dx,#0x3c4 ! д��0x3c4�˿������Ķ���/��չ�Ĵ���Ӧ�ûᵼ��Cirrus
297 out dx,ax ! ��ʾ����ֹ��չ���ܡ�
298 inc dx
299 in al,dx ! �����չ������ı���ֹ����ô��ʱ�����ֵӦ��Ϊ0��
300 and al,al ! �����Ϊ0���ʾ����Cirrus��ʾ������ת���������������
301 jnz nocirr
302 mov al,bh ! ��Cirrus��ʾ���������õ�286�б�����bh�еġ�Eagle
303 out dx,al ! ID��ԭֵ�����¿���Cirrus����չ���ܡ���ʱ��ȡ�ķ���
304 in al,dx ! ֵӦ��Ϊ1�������ǣ�����Ȼ˵������Cirrus��ʾ����
305 cmp al,#0x01
306 jne nocirr
307 call rst3d4 ! �ָ�CRT����������ʾ��ʼ��ַ���ֽڼĴ������ݡ�
308 lea si,dsccirrus ! siָ��Cirrus��ʾ���Ŀ�ѡ����ֵ��diָ����չģʽ����
309 lea di,mocirrus ! �Ͷ�Ӧģʽ�š�Ȼ����ת��selmod��ȥѡ����ʾģʽ��
310 lea cx,selmod
311 jmp cx
! ���ӳ������ñ�����bl�е�ֵ����278�У��ָ�CRT����������ʾ��ʼ��ַ���ֽڼĴ������ݡ�
312 rst3d4: mov dx,#0x3d4
313 mov al,bl
314 xor ah,ah
315 shl ax,#8
316 add ax,#0x0c
317 out dx,ax ! ע�⣬����word������� al ��0x3d4��ah ��0x3d5��
318 ret
! ���ڼ��ϵͳ���Dz���Everex��ʾ���������������ж�int 0x10����0x70��ax =0x7000��
! bx=0x0000������Everex����չ��ƵBIOS���ܡ�����Everes������ʾ�������жϵ���Ӧ��
! �᷵��ģ��״̬���������·�����Ϣ��
! al = 0x70�����ǻ���Trident��Everex��ʾ����
! cl = ��ʾ�����ͣ�00-��ɫ��01-CGA��02-EGA��03-���ֶ�Ƶ��04-PS/2��05-IBM 8514��06-SVGA��
! ch = ���ԣ�λ7-6��00-256K��01-512K��10-1MB��11-2MB��λ4-����VGA������λ0-6845ģ�⡣
! dx = �忨�ͺţ�λ15-4�������ͱ�ʶ�ţ�λ3-0����������ʶ�š�
! 0x2360-Ultragraphics II��0x6200-Vision VGA��0x6730-EVGA��0x6780-Viewpoint��
! di = ��BCD���ʾ����ƵBIOS�汾�š�
319 nocirr: call rst3d4 ! Check Everex 'clues'
320 mov ax,#0x7000 ! ����ax = 0x7000, bx=0x0000������int 0x10��
321 xor bx,bx
322 int 0x10
323 cmp al,#0x70 ! ����Everes��ʾ����al��Ӧ�÷���ֵ0x70��
324 jne noevrx
325 shr dx,#4 ! ���ɰ������ţ�λ3-0����
326 cmp dx,#0x678 ! �����ͺ���0x678��ʾ��һ��Trident��ʾ��������ת��
327 je istrid
328 cmp dx,#0x236 ! �����ͺ���0x236��ʾ��һ��Trident��ʾ��������ת��
329 je istrid
330 lea si,dsceverex ! ��siָ��Everex��ʾ���Ŀ�ѡ����ֵ������diָ����չ
331 lea di,moeverex ! ģʽ������ģʽ���б���Ȼ����ת��selmodȥִ��ѡ��
332 lea cx,selmod ! ��ʾģʽ�IJ�����
333 jmp cx
334 istrid: lea cx,ev2tri ! ��Trident���͵�Everex��ʾ��������ת��ev2tri������
335 jmp cx
! ���ڼ���Dz���Genoa��ʾ������ʽ�Ǽ������ƵBIOS�е��������ִ���0x77��0x00��0x66��
! 0x99����ע�⣬��ʱes�Ѿ��ڵ�220�б����ó�ָ��VGA����ROM BIOS���ڵĶ�0xc000��
336 noevrx: lea si,idgenoa ! Check Genoa 'clues'
337 xor ax,ax ! ��ds:siָ���597���ϵ��������ִ���
338 seg es
339 mov al,[0x37] ! ȡVGA����BIOS��0x37����ָ�루��ָ������������
340 mov di,ax ! ��˴�ʱes:diָ���������ִ���ʼ����
341 mov cx,#0x04
342 dec si
343 dec di
344 l1: inc si ! Ȼ��ѭ���Ƚ���4���ֽڵ��������ִ���
345 inc di
346 mov al,(si)
347 seg es
348 and al,(di)
349 cmp al,(si)
350 loope l1
351 cmp cx,#0x00 ! ����������ִ���ȫ��ͬ�����ʾ��Genoa��ʾ����
352 jne nogen ! ������תȥ����������͵���ʾ����
353 lea si,dscgenoa ! ��siָ��Genoa��ʾ���Ŀ�ѡ����ֵ������diָ����չ
354 lea di,mogenoa ! ģʽ������ģʽ���б���Ȼ����ת��selmodȥִ��ѡ��
355 lea cx,selmod ! ��ʾģʽ�IJ�����
356 jmp cx
! ���ڼ���Dz���Paradise��ʾ����ͬ���Dz��ñȽ���ʾ����BIOS������������VGA=�����ķ�ʽ��
357 nogen: lea si,idparadise ! Check Paradise 'clues'
358 mov di,#0x7d ! es:diָ��VGA ROM BIOS��0xc000:0x007d�����ô�Ӧ����
359 mov cx,#0x04 ! 4���ַ���VGA=����
360 repe
361 cmpsb
362 jne nopara ! ���в�ͬ���ַ�����ʾ����Paradise��ʾ����������ת��
363 lea si,dscparadise ! ������siָ��Paradise��ʾ���Ŀ�ѡ����ֵ������diָ
364 lea di,moparadise ! ����չģʽ������ģʽ���б���Ȼ����ת��selmod��ȥѡ
365 lea cx,selmod ! ����Ҫʹ�õ���ʾģʽ��
366 jmp cx
! ���ڼ���Dz���Trident��TVGA����ʾ����TVGA��ʾ�������ģʽ���ƼĴ���1��0x3c4�˿�����
! ��0x0e����λ3--0��64K�ڴ�ҳ�����ֵ������ֶ�ֵ��һ�����ԣ���д��ʱ��������Ҫ���Ȱ�
! ֵ��0x02��������������д�룻����ȡ��ֵʱ����Ҫִ���������������ǰ��ֵӦ����д
! ����ٶ�ȡ��ֵ��ͬ���������������������������Dz���Trident��ʾ����
367 nopara: mov dx,#0x3c4 ! Check Trident 'clues'
368 mov al,#0x0e ! �����ڶ˿�0x3c4���������0x0e������ģʽ���ƼĴ���1��
369 out dx,al ! Ȼ���0x3c5���ݶ˿ڶ���üĴ���ԭֵ�����ݴ���ah�С�
370 inc dx
371 in al,dx
372 xchg ah,al
373 mov al,#0x00 ! Ȼ��������üĴ���д��0x00���ٶ�ȡ��ֵ��al��
374 out dx,al ! д��0x00���൱�ڡ�ԭֵ��0x02���0x02���д��ֵ��
375 in al,dx ! �������Trident��ʾ������˺�����ֵӦ����0x02��
376 xchg al,ah ! ������al=ԭģʽ���ƼĴ���1��ֵ��ah=����ȡ��ֵ��
! �����������Ӣ��ע���ǡ������...���в�û��Ҫ��������������������ҵ�Trident��ʾ��
! �����á����������������Ļ�ͻ��ģ��...�����⼸�и�����Ӣ��ע�͵����ִ�����²�����
! ���bl��ԭģʽ���ƼĴ���1��λ1����λ״̬�Ļ��ͽ��临λ������ͽ�λ1��λ��
! ʵ�����⼸�������Ƕ�ԭģʽ���ƼĴ���1��ִֵ����� 0x02�IJ�����Ȼ���ý��ֵȥ����
! ���ָ���ԭ�Ĵ���ֵ��
377 mov bl,al ! Strange thing ... in the book this wasn't
378 and bl,#0x02 ! necessary but it worked on my card which
379 jz setb2 ! is a trident. Without it the screen goes
380 and al,#0xfd ! blurred ...
381 jmp clrb2 !
382 setb2: or al,#0x02 !
383 clrb2: out dx,al
384 and ah,#0x0f ! ȡ375��������ֵ��ҳ������ֶΣ�λ3--0�������
385 cmp ah,#0x02 ! ���ֶ�ֵ����0x02�����ʾ��Trident��ʾ����
386 jne notrid
387 ev2tri: lea si,dsctrident ! ��Trident��ʾ����������siָ�����ʾ���Ŀ�ѡ����
388 lea di,motrident ! ֵ�б�����diָ���Ӧ��չģʽ������ģʽ���б���Ȼ
389 lea cx,selmod ! ����ת��selmodȥִ��ģʽѡ�������
390 jmp cx
! ���ڼ���Dz���Tseng��ʾ����ET4000AX��ET4000/W32�ࣩ�������Ƕ�0x3cd�˿ڶ�Ӧ�Ķ�
! ѡ��Segment Select���Ĵ���ִ�ж�д�������üĴ�����4λ��λ7--4����Ҫ���ж�������
! 64KB�κţ�Bank number������4λ��λ3--0����ָ��Ҫд�Ķκš����ָ����ѡ��Ĵ�����
! ��ֵ�� 0x55����ʾ����д��6��64KB�Σ�����ô����Tseng��ʾ����˵���Ѹ�ֵд��Ĵ���
! ���ٶ���Ӧ�û���0x55��
391 notrid: mov dx,#0x3cd ! Check Tseng 'clues'
392 in al,dx ! Could things be this simple ! :-)
393 mov bl,al ! �ȴ�0x3cd�˿ڶ�ȡ��ѡ��Ĵ���ԭֵ����������bl�С�
394 mov al,#0x55 ! Ȼ��������üĴ�����д��0x55���ٶ��벢����ah�С�
395 out dx,al
396 in al,dx
397 mov ah,al
398 mov al,bl ! ���Żָ��üĴ�����ԭֵ��
399 out dx,al
400 cmp ah,#0x55 ! �����ȡ�ľ�������д���ֵ���������Tseng��ʾ����
401 jne notsen
402 lea si,dsctseng ! ������siָ��Tseng��ʾ���Ŀ�ѡ����ֵ���б�����di
403 lea di,motseng ! ָ���Ӧ��չģʽ������ģʽ���б���Ȼ����ת��selmod
404 lea cx,selmod ! ȥִ��ģʽѡ�������
405 jmp cx
! �������Dz���Video7��ʾ�����˿�0x3c2�ǻ������Ĵ���д�˿ڣ���0x3cc�ǻ������Ĵ�
! �����˿ڡ��üĴ�����λ0�ǵ�ɫ/��ɫ��־�����Ϊ0���ʾ�ǵ�ɫ�������Dz�ɫ���ж��Dz���
! Video7��ʾ���ķ�ʽ������������ʾ����CRT������չ��ʶ�Ĵ�������������0x1f�����üĴ���
! ��ֵʵ���Ͼ����Դ���ʼ��ַ���ֽڼĴ�����������0x0c�������ݺ�0xea�������������ֵ��
! �������ֻҪ���Դ���ʼ��ַ���ֽڼĴ�����д��һ���ض�ֵ��Ȼ��ӱ�ʶ�Ĵ����ж�ȡ��ʶֵ
! �����жϼ��ɡ�
! ͨ����������ʾ��������Video7��ʾ���ļ����������ǿ�֪������ͨ����Ϊ�����������衣
! ���ȶ�ȡ�����������Ҫ�õ��ļĴ���ԭֵ��Ȼ��ʹ���ض�����ֵ����д��Ͷ�������������
! ��ԭ�Ĵ���ֵ���Լ���������жϡ�
406 notsen: mov dx,#0x3cc ! Check Video7 'clues'
407 in al,dx
408 mov dx,#0x3b4 ! ������dxΪ��ɫ��ʾCRT���������Ĵ����˿ں�0x3b4��
409 and al,#0x01 ! ����������Ĵ�����λ0����0����ɫ����ֱ����ת��
410 jz even7 ! ����dx����Ϊ��ɫ��ʾCRT���������Ĵ����˿ں�0x3d4��
411 mov dx,#0x3d4
412 even7: mov al,#0x0c ! ���üĴ���������Ϊ0x0c����Ӧ�Դ���ʼ��ַ���ֽڼĴ�����
413 out dx,al
414 inc dx
415 in al,dx ! ��ȡ��ʾ�ڴ���ʼ��ַ���ֽڼĴ������ݣ���������bl�С�
416 mov bl,al
417 mov al,#0x55 ! Ȼ�����Դ���ʼ��ַ���ֽڼĴ�����д��ֵ0x55���ٶ�ȡ������
418 out dx,al
419 in al,dx
420 dec dx ! Ȼ��ͨ��CRTC�����Ĵ����˿�0x3b4��0x3d4ѡ����������
421 mov al,#0x1f ! 0x1f��Video7��ʾ����ʶ�Ĵ������üĴ�������ʵ���Ͼ���
422 out dx,al ! �Դ���ʼ��ַ���ֽں�0xea������������Ľ��ֵ��
423 inc dx
424 in al,dx ! ��ȡVideo7��ʾ����ʶ�Ĵ���ֵ����������bh�С�
425 mov bh,al
426 dec dx ! Ȼ����ѡ���Դ���ʼ��ַ���ֽڼĴ������ָ���ԭֵ��
427 mov al,#0x0c
428 out dx,al
429 inc dx
430 mov al,bl
431 out dx,al
432 mov al,#0x55 ! �����������֤��Video7��ʾ����ʶ�Ĵ���ֵ�����Դ���ʼ
433 xor al,#0xea ! ��ַ���ֽں�0xea������������Ľ��ֵ�������0x55
434 cmp al,bh ! ��0xea�����������Ľ����Ӧ�õ��ڱ�ʶ�Ĵ����IJ���ֵ��
435 jne novid7 ! ������Video7��ʾ����������Ĭ����ʾ����ֵ��492�У���
436 lea si,dscvideo7 ! ��Video7��ʾ����������siָ�����ʾ������ֵ������di
437 lea di,movideo7 ! ָ����չģʽ������ģʽ���б���
! ����������������жϳ�����ʾ�������Լ�ȡ�õ������չģʽ��Ϣ��siָ�������ֵ�б���di
! ָ����չģʽ������ģʽ���б�������ʾ�û�ѡ����õ���ʾģʽ�������ó���Ӧ��ʾģʽ�����
! �ӳ���ϵͳ��ǰ���õ���Ļ����ֵ��ah = ������al=�����������磬���ϵͳ����ATI��ʾ����
! ��ô��Ļ�ϻ���ʾ������Ϣ��
! Mode: COLSxROWS:
! 0. 132 x 25
! 1. 132 x 44
! Choose mode by pressing the corresponding number.
!
! ��γ�����������Ļ����ʾNULL��β���ַ�����Ϣ��Mode: COLSxROWS:����
438 selmod: push si
439 lea si,msg2
440 call prtstr
441 xor cx,cx
442 mov cl,(di) ! ��ʱcl���Ǽ�������ʾ������չģʽ������
443 pop si
444 push si
445 push cx
! Ȼ����ÿһ������ʾ����ǰ��ʾ����ѡ�����չģʽ����ֵ�����û�ѡ�á�
446 tbl: pop bx ! bx = ��ʾ������չģʽ�ܸ�����
447 push bx
448 mov al,bl
449 sub al,cl
450 call dprnt ! ��ʮ���Ƹ�ʽ��ʾal�е�ֵ��
451 call spcing ! ��ʾһ�����ٿ�4���ո�
452 lodsw ! ��ax�м���siָ�������ֵ�����siָ����һ��wordֵ��
453 xchg al,ah ! ����λ�ú�al = ������
454 call dprnt ! ��ʾ������
455 xchg ah,al ! ��ʱal��������ֵ��
456 push ax
457 mov al,#0x78 ! ��ʾһ��С��x�������˺š�
458 call prnt1
459 pop ax ! ��ʱal��������ֵ��
460 call dprnt ! ��ʾ������
461 call docr ! �س����С�
462 loop tbl ! ����ʾ��һ������ֵ��cx����չģʽ����ֵ�ݼ�1��
! ����չģʽ����ֵ����ʾ֮����ʾ��Choose mode by pressing the corresponding number.����
! Ȼ��Ӽ��̿ڶ�ȡ�û�������ɨ���룬���ݸ�ɨ����ȷ���û�ѡ�������ֵģʽ�ţ�������ROM
! BIOS����ʾ�ж�int 0x10����0x00��������Ӧ����ʾģʽ��
! ��468�е���ģʽ����ֵ+0x80�����������ּ�-1���ɿ�ɨ���롣����0--9���ּ������ǵ��ɿ�
! ɨ����ֱ��ǣ�0 - 0x8B��1 - 0x82��2 - 0x83��3 - 0x84��4 - 0x85��
! 5 - 0x86��6 - 0x87��7 - 0x88��8 - 0x89��9 - 0x8A��
! ��ˣ������ȡ�ļ����ɿ�ɨ����С��0x82�ͱ�ʾ�������ּ������ɨ�������0x8B���ʾ�û�
! ��������0����
463 pop cx ! cl������ʾ����չģʽ�ܸ���ֵ��
464 call docr
465 lea si,msg3 ! ��ʾ���밴��Ӧ���ּ���ѡ��ģʽ����
466 call prtstr
467 pop si ! ����ԭ����ֵָ�루ָ����ʾ������ֵ����ʼ������
468 add cl,#0x80 ! cl + 0x80 = ��Ӧ�����ּ�-1�����ɿ�ɨ���롣
469 nonum: in al,#0x60 ! Quick and dirty...
470 cmp al,#0x82 ! �������ɿ�ɨ����С��0x82���ʾ�������ּ������ɸü���
471 jb nonum
472 cmp al,#0x8b ! �������ɿ�ɨ�������0x8b����ʾ���������ּ�0��
473 je zero
474 cmp al,cl ! ��ɨ���������չģʽ����ֵ��Ӧ�����ɨ����ֵ����ʾ
475 ja nonum ! �����ֵ������Χ�������ּ����ɿ�ɨ���롣�����ʾ
476 jmp nozero ! �û����²��ɿ���һ����0���ְ�����
! ������ɿ�ɨ����ת���ɶ�Ӧ�����ְ���ֵ��Ȼ�����ø�ֵ��ģʽ������ģʽ���б���ѡ���Ӧ��
! ��ģʽ�š����ŵ��û���ROM BIOS�ж�int 0x10����0����Ļ���ó�ģʽ��ָ����ģʽ�������
! ����ģʽ�Ŵ���ʾ������ֵ����ѡ����ax�з��ض�Ӧ������ֵ��
477 zero: sub al,#0x0a ! al = 0x8b - 0x0a = 0x81��
478 nozero: sub al,#0x80 ! �ټ�ȥ0x80�Ϳ��Եõ��û�ѡ���˵ڼ���ģʽ��
479 dec al ! ��0�������
480 xor ah,ah ! int 0x10��ʾ���ܺ�=0��������ʾģʽ����
481 add di,ax
482 inc di ! diָ���Ӧ��ģʽ�ţ�������1��ģʽ�����ֽ�ֵ����
483 push ax
484 mov al,(di) ! ȡģʽ����al�У�������ϵͳBIOS��ʾ�жϹ���0��
485 int 0x10
486 pop ax
487 shl ax,#1 ! ģʽ�ų�2��ת����Ϊ����ֵ���ж�Ӧֵ��ָ�롣
488 add si,ax
489 lodsw ! ȡ��Ӧ����ֵ��ax�У�ah = ������al = ��������
490 pop ds ! �ָ���216�б����dsԭֵ����ax�з��ص�ǰ��ʾ����ֵ��
491 ret
! �����������������ʾ������ô����ֻ�ò���Ĭ�ϵ�80 x 25 �ı�����ֵ��
492 novid7: pop ds ! Here could be code to support standard 80x50,80x30
493 mov ax,#0x5019
494 ret
496 ! Routine that 'tabs' to next col.
! ����ƶ�����һ�Ʊ�λ���ӳ���
! ��ʾһ�����ַ�'.'��4���ո�
498 spcing: mov al,#0x2e ! ��ʾһ�����ַ�'.'��
499 call prnt1
500 mov al,#0x20
501 call prnt1
502 mov al,#0x20
503 call prnt1
504 mov al,#0x20
505 call prnt1
506 mov al,#0x20
507 call prnt1
508 ret
510 ! Routine to print asciiz-string at DS:SI
! ��ʾλ��DS:SI����NULL��0x00����β���ַ�����
512 prtstr: lodsb
513 and al,al
514 jz fin
515 call prnt1 ! ��ʾal�е�һ���ַ���
516 jmp prtstr
517 fin: ret
519 ! Routine to print a decimal value on screen, the value to be
520 ! printed is put in al (i.e 0-255).
! ��ʾʮ�������ֵ��ӳ�����ʾֵ���ڼĴ���al�У�0--255����
522 dprnt: push ax
523 push cx
524 mov ah,#0x00
525 mov cl,#0x0a
526 idiv cl
527 cmp al,#0x09
528 jbe lt100
529 call dprnt
530 jmp skip10
531 lt100: add al,#0x30
532 call prnt1
533 skip10: mov al,ah
534 add al,#0x30
535 call prnt1
536 pop cx
537 pop ax
538 ret
540 ! Part of above routine, this one just prints ascii al
! �����ӳ����һ���֡���ʾal�е�һ���ַ���
! ���ӳ���ʹ���ж�0x10��0x0E���ܣ��Ե紫��ʽ����Ļ��дһ���ַ��������Զ��Ƶ���һ��
! λ�ô������д��һ�й��ͻ��ƶ�����һ�п�ʼ��������Ѿ�д��һ�����һ�У���������Ļ
! �����Ϲ���һ�С��ַ�0x07��BEL����0x08��BS����0x0A(LF)��0x0D��CR������Ϊ�������ʾ��
! ���룺AL -- ��д�ַ���BH -- ��ʾҳ�ţ�BL -- ǰ����ʾɫ��ͼ�η�ʽʱ����
542 prnt1: push ax
543 push cx
544 mov bh,#0x00 ! ��ʾҳ�档
545 mov cx,#0x01
546 mov ah,#0x0e
547 int 0x10
548 pop cx
549 pop ax
550 ret
552 ! Prints <CR> + <LF> ! ��ʾ�س�+���С�
554 docr: push ax
555 push cx
556 mov bh,#0x00
557 mov ah,#0x0e
558 mov al,#0x0a
559 mov cx,#0x01
560 int 0x10
561 mov al,#0x0d
562 int 0x10
563 pop cx
564 pop ax
565 ret
! ȫ������������ʼ�������������ɶ��8�ֽڳ�������������ɡ����������3���������
! ��1�����ã�568�У���������ڡ���2����ϵͳ�������������570-573�У�����3����ϵ
! ͳ���ݶ�������(575-578��)��
567 gdt:
568 .word 0,0,0,0 ! dummy ! ��1�������������á�
! ��GDT���������ƫ������0x08�������ں˴����ѡ�����ֵ��
570 .word 0x07FF ! 8Mb - limit=2047 (0--2047�������2048*4096=8Mb)
571 .word 0x0000 ! base address=0
572 .word 0x9A00 ! code read/exec ! �����Ϊֻ������ִ�С�
573 .word 0x00C0 ! granularity=4096, 386 ! ������Ϊ4096��32λģʽ��
! ��GDT���������ƫ������0x10�������ں����ݶ�ѡ�����ֵ��
575 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
576 .word 0x0000 ! base address=0
577 .word 0x9200 ! data read/write ! ���ݶ�Ϊ�ɶ���д��
578 .word 0x00C0 ! granularity=4096, 386 ! ������Ϊ4096��32λģʽ��
! �����Ǽ����ж����������Ĵ���idtr��ָ��lidtҪ���6�ֽڲ�������ǰ2�ֽ���IDT����
! ������4�ֽ���idt�������Ե�ַ�ռ��е�32λ����ַ��CPUҪ���ڽ��뱣��ģʽ֮ǰ����
! ��IDT�����������������һ������Ϊ0�Ŀձ���
580 idt_48:
581 .word 0 ! idt limit=0
582 .word 0,0 ! idt base=0L
! ���Ǽ���ȫ�����������Ĵ���gdtr��ָ��lgdtҪ���6�ֽڲ�������ǰ2�ֽ���gdt������
! ������4�ֽ��� gdt�������Ի���ַ������ȫ�ֱ���������Ϊ 2KB��0x7ff���ɣ�����Ϊÿ8
! �ֽ����һ��������������Ա��й����� 256�4�ֽڵ����Ի���ַΪ 0x0009<<16 +
! 0x0200 + gdt����0x90200 + gdt��(����gdt��ȫ�ֱ��ڱ�������е�ƫ�Ƶ�ַ����205��)
584 gdt_48:
585 .word 0x800 ! gdt limit=2048, 256 GDT entries
586 .word 512+gdt,0x9 ! gdt base = 0X9xxxx
588 msg1: .ascii "Press <RETURN> to see SVGA-modes available or any other key to continue."
589 db 0x0d, 0x0a, 0x0a, 0x00
590 msg2: .ascii "Mode: COLSxROWS:"
591 db 0x0d, 0x0a, 0x0a, 0x00
592 msg3: .ascii "Choose mode by pressing the corresponding number."
593 db 0x0d, 0x0a, 0x00
! ������4����ʾ�����������ݴ���
595 idati: .ascii "761295520"
596 idcandt: .byte 0xa5 ! ���idcandt��˼��ID of Chip AND Tech.
597 idgenoa: .byte 0x77, 0x00, 0x66, 0x99
598 idparadise: .ascii "VGA="
! �����Ǹ�����ʾ����ʹ�õ���չģʽ�����Ͷ�Ӧ��ģʽ���б�������ÿһ�е�1���ֽ���ģʽ��
! ��ֵ������һЩֵ���ж�0x10����0��AH=0����ʹ�õ�ģʽ�š������602�п�֪������ATI
! ���ӵ���ʾ�������˱�ģʽ�����ʹ��������չģʽ��0x23��0x33��
600 ! Manufacturer: Numofmodes: Mode:
! ���ң� ģʽ������ ģʽ�б���
602 moati: .byte 0x02, 0x23, 0x33
603 moahead: .byte 0x05, 0x22, 0x23, 0x24, 0x2f, 0x34
604 mocandt: .byte 0x02, 0x60, 0x61
605 mocirrus: .byte 0x04, 0x1f, 0x20, 0x22, 0x31
606 moeverex: .byte 0x0a, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
607 mogenoa: .byte 0x0a, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
608 moparadise: .byte 0x02, 0x55, 0x54
609 motrident: .byte 0x07, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
610 motseng: .byte 0x05, 0x26, 0x2a, 0x23, 0x24, 0x22
611 movideo7: .byte 0x06, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45
! �����Ǹ�������VGA��ʾ����ʹ�õ�ģʽ��Ӧ���С���ֵ�б��������615�б�ʾATI��ʾ����
! ����չģʽ���С���ֵ�ֱ��� 132 x 25�� 132 x 44��
613 ! msb = Cols lsb = Rows:
! ���ֽ�=���� ���ֽ�=������
615 dscati: .word 0x8419, 0x842c ! ATI���������С���ֵ��
616 dscahead: .word 0x842c, 0x8419, 0x841c, 0xa032, 0x5042 ! Ahead��������ֵ��
617 dsccandt: .word 0x8419, 0x8432
618 dsccirrus: .word 0x8419, 0x842c, 0x841e, 0x6425
619 dsceverex: .word 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
620 dscgenoa: .word 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
621 dscparadise: .word 0x8419, 0x842b
622 dsctrident: .word 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
623 dsctseng: .word 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
624 dscvideo7: .word 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
626 .text
627 endtext:
628 .data
629 enddata:
630 .bss
631 endbss:
1 /*
2 * linux/boot/head.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * head.s contains the 32-bit startup code.
9 *
10 * NOTE!!! Startup happens at absolute address 0x00000000, which is also where
11 * the page directory will exist. The startup code will be overwritten by
12 * the page directory.
13 */
/*
* head.s����32λ�������롣
* ע��!!! 32λ���������ǴӾ��Ե�ַ0x00000000��ʼ�ģ�����Ҳͬ����ҳĿ¼�����ڵĵط���
* ���������������뽫��ҳĿ¼���ǵ���
*/
14 .text
15 .globl _idt,_gdt,_pg_dir,_tmp_floppy_area
16 _pg_dir: # ҳĿ¼�����������
# �ٴ�ע��!!! �����Ѿ�����32λ����ģʽ����������$0x10�����ǰѵ�ַ0x10װ�����
# �μĴ�������������ʵ��ȫ�ֶ����������е�ƫ��ֵ�����߸�ȷ��˵��һ������������
# ��ѡ������й�ѡ�����˵����μ�setup.s��193���µ�˵��������$0x10�ĺ���������
# ��Ȩ��0(λ0-1=0)��ѡ��ȫ����������(λ2=0)��ѡ����е�2��(λ3-15=2)��������ָ
# ����е����ݶ�����������������ľ�����ֵ�μ�ǰ��setup.s��212��213�У�
# �������ĺ����ǣ�����ds,es,fs,gsΪsetup.s �й�������ݶΣ�ȫ�ֶ�����������2�
# ��ѡ���=0x10��������ջ������stack_startָ���user_stack��������Ȼ��ʹ�ñ�����
# ���涨������ж�����������ȫ�ֶ�����������ȫ�ֶ��������г�ʼ������setup.s�еĻ���
# һ������������8MB�ij���16MB��stack_start������kernel/sched.c��69�С�����ָ��
# user_stack����ĩ�˵�һ����ָ�롣��23����������ʹ�õ�ջ�����ҳ�Ϊϵͳջ�������ƶ���
# ����0ִ�У�init/main.c��137�У��Ժ��ջ�ͱ���������0������1��ͬʹ�õ��û�ջ�ˡ�
17 startup_32: # 18-22�����ø������ݶμĴ�����
18 movl $0x10,%eax # ����GNU��࣬ÿ��ֱ�Ӳ�����Ҫ��'$'��ʼ�������ʾ��ַ��
# ÿ���Ĵ�������Ҫ��'%'��ͷ��eax��ʾ��32λ��ax�Ĵ�����
19 mov %ax,%ds
20 mov %ax,%es
21 mov %ax,%fs
22 mov %ax,%gs
23 lss _stack_start,%esp # ��ʾ_stack_start��ss:esp������ϵͳ��ջ��
# stack_start������kernel/sched.c��69��
24 call setup_idt # ���������ж����������ӳ���
25 call setup_gdt # ��������ȫ�����������ӳ���
26 movl $0x10,%eax # reload all the segment registers
27 mov %ax,%ds # after changing gdt. CS was already
28 mov %ax,%es # reloaded in 'setup_gdt'
29 mov %ax,%fs # ��Ϊ����gdt��������Ҫ����װ�����еĶμĴ�����
30 mov %ax,%gs # CS����μĴ����Ѿ���setup_gdt�����¼��ع��ˡ�
# ���ڶ��������еĶ�����setup.s�е�8MB�ij��˱��������õ�16MB����setup.s��208-216
# �ͱ���������235-236�У�����������ٴζ����жμĴ���ִ�м��ز����DZ���ġ����⣬ͨ��
# ʹ��bochs���ٹ۲죬�������CS�ٴ�ִ�м��أ���ô��ִ�е�26��ʱCS����β��ɼ�������
# ��������8MB����������Ӧ�����¼���CS����������setup.s�е��ں˴�����������뱾������
# �������õĴ�������������˶����������ಿ����ȫһ����8MB�������ں˳�ʼ���β�����
# ���⣬�������Ժ��ں�ִ�й����жμ���תʱ�����¼���CS���������û�м�������û���ó���
# ������
# ��Ը����⣬Ŀǰ�ں��о��ڵ�25��֮��������һ������תָ�'ljmp $(__KERNEL_CS),$1f'��
# ��ת����26����ȷ��CSȷʵ�ֱ����¼��ء�
31 lss _stack_start,%esp
# 32-36�����ڲ���A20��ַ���Ƿ��Ѿ����������õķ��������ڴ��ַ0x000000��д������
# һ����ֵ��Ȼ���ڴ��ַ0x100000(1M)���Ƿ�Ҳ�������ֵ�����һֱ��ͬ�Ļ�����һֱ
# �Ƚ���ȥ��Ҳ����ѭ������������ʾ��ַA20��û��ѡͨ������ں˾Ͳ���ʹ��1MB�����ڴ档
#
# 33���ϵ�'1:'��һ���ֲ����Ź��ɵı�š�����ɷ��ź��һ��ð����ɡ���ʱ�÷��ű�ʾ�
# λ�ü�����Active location counter���ĵ�ǰֵ����������Ϊָ��IJ��������ֲ��������ڰ���
# �������ͱ����Ա��ʱʹ��һЩ���ơ�����10���ֲ������������������������ظ�ʹ�á���Щ����
# ��ʹ������'0'��'1'��...��'9'�����á�Ϊ�˶���һ���ֲ����ţ���ѱ��д��'N:'��ʽ������N
# ��ʾһ�����֣���Ϊ��������ǰ��������������ţ���Ҫд��'Nb'������N�Ƕ�����ʱʹ�õ�
# ���֡�Ϊ������һ���ֲ���ŵ���һ�����壬��Ҫд��'Nf'������N��10��ǰ������֮һ������
# 'b'��ʾ�����backwards������'f'��ʾ����ǰ��forwards�������ڻ������ijһ�����������
# �������/��ǰ����10����ţ���Զ��10������
32 xorl %eax,%eax
33 1: incl %eax # check that A20 really IS enabled
34 movl %eax,0x000000 # loop forever if it isn't
35 cmpl %eax,0x100000
36 je 1b # '1b'��ʾ���(backward)��ת�����1ȥ��33�У���
# ����'5f'���ʾ��ǰ(forward)��ת�����5ȥ��
37 /*
38 * NOTE! 486 should set bit 16, to check for write-protect in supervisor
39 * mode. Then it would be unnecessary with the "verify_area()"-calls.
40 * 486 users probably want to set the NE (#5) bit also, so as to use
41 * int 16 for math errors.
42 */
/*
* ע��! ��������γ����У�486Ӧ�ý�λ16��λ���Լ���ڳ����û�ģʽ�µ�д����,
* �˺� "verify_area()" ���þͲ���Ҫ�ˡ�486���û�ͨ��Ҳ���뽫NE(#5)��λ���Ա�
* ����ѧЭ�������ij���ʹ��int 16��
*/
# ����ԭע�����ᵽ��486 CPU��CR0���ƼĴ�����λ16��д������־WP��Write-Protect����
# ���ڽ�ֹ�����û����ij�����һ���û�ֻ��ҳ���н���д�������ñ�־��Ҫ���ڲ���ϵͳ�ڴ���
# �½���ʱʵ��дʱ���ƣ�copy-on-write��������
# ������γ���43-65�����ڼ����ѧЭ������оƬ�Ƿ���ڡ��������Ŀ��ƼĴ���CR0����
# �������Э�������������ִ��һ��Э������ָ���������Ļ���˵��Э������оƬ�����ڣ�
# ��Ҫ����CR0�е�Э����������λEM��λ2��������λЭ���������ڱ�־MP��λ1����
43 movl %cr0,%eax # check math chip
44 andl $0x80000011,%eax # Save PG,PE,ET
45 /* "orl $0x10020,%eax" here for 486 might be good */
46 orl $2,%eax # set MP
47 movl %eax,%cr0
48 call check_x87
49 jmp after_page_tables # ��ת��135�С�
50
51 /*
52 * We depend on ET to be correct. This checks for 287/387.
53 */
/*
* ����������ET��־����ȷ�������287/387�������
*/
# ����fninit��fstsw����ѧЭ��������80287/80387����ָ�
# finit ��Э������������ʼ����������Э����������һ��δ����ǰ����Ӱ�����֪״̬������
# �������ΪĬ��ֵ�����״̬�ֺ����и���ջʽ�Ĵ������ǵȴ���ʽ������ָ�fninit��������
# Э��������ִֹ�е�ǰ����ִ�е��κ���ǰ������������fstsw ָ��ȡЭ��������״̬�֡����ϵ
# ͳ�д���Э�������Ļ�����ô��ִ����fninitָ�����״̬�ֵ��ֽڿ϶�Ϊ0��
54 check_x87:
55 fninit # ��Э������������ʼ�����
56 fstsw %ax # ȡЭ������״̬�ֵ�ax�Ĵ����С�
57 cmpb $0,%al # ��ʼ����״̬��Ӧ��Ϊ0������˵��Э�����������ڡ�
58 je 1f /* no coprocessor: have to set bits */
59 movl %cr0,%eax # �����������ǰ��ת�����1���������дcr0��
60 xorl $6,%eax /* reset MP, set EM */
61 movl %eax,%cr0
62 ret
# ������һ�������ָʾ�����京����ָ�洢�߽���������"2"��ʾ�����Ĵ�������ݵ�ƫ��λ��
# ��������ֵַ���2����λΪ���λ�ã�2^2��������4�ֽڷ�ʽ�����ڴ��ַ����������GNU as
# ֱ��ʱд�������ֵ����2�Ĵη�ֵ�ˡ�ʹ�ø�ָʾ����Ŀ����Ϊ�����32λCPU�����ڴ��д���
# �����ݵ��ٶȺ�Ч�ʡ��μ���������ϸ˵����
# ����������ֽ�ֵ��80287Э������ָ��fsetpm�Ļ����롣�������ǰ�80287����Ϊ����ģʽ��
# 80387�����ָ����ҽ���Ѹ�ָ����ǿղ�����
63 .align 2
64 1: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ # 287Э�������롣
65 ret
66
67 /*
68 * setup_idt
69 *
70 * sets up a idt with 256 entries pointing to
71 * ignore_int, interrupt gates. It then loads
72 * idt. Everything that wants to install itself
73 * in the idt-table may do so themselves. Interrupts
74 * are enabled elsewhere, when we can be relatively
75 * sure everything is ok. This routine will be over-
76 * written by the page tables.
77 */
/*
* ��������������ж����������ӳ��� setup_idt
*
* ���ж���������idt���óɾ���256�������ָ��ignore_int�ж��š�Ȼ������ж�
* ���������Ĵ���(��lidtָ��)������ʵ�õ��ж����Ժ��ٰ�װ���������������ط���Ϊһ��
* ������ʱ�ٿ����жϡ����ӳ��ᱻҳ�����ǵ���
*/
# �ж����������е�����ȻҲ��8�ֽ���ɣ������ʽ��ȫ�ֱ��еIJ�ͬ������Ϊ��������
# (Gate Descriptor)������0-1,6-7�ֽ���ƫ������2-3�ֽ���ѡ�����4-5�ֽ���һЩ��־��
# ��δ���������edx��eax��������ó�8�ֽ�Ĭ�ϵ��ж�������ֵ��Ȼ����idt��ÿһ����
# �����ø�����������256�eax������������4�ֽڣ�edx���и�4�ֽڡ��ں������ij�ʼ
# �������л��滻��װ��Щ����ʵ�õ��ж��������
78 setup_idt:
79 lea ignore_int,%edx # ��ignore_int����Ч��ַ��ƫ��ֵ��ֵ��edx�Ĵ���
80 movl $0x00080000,%eax # ��ѡ���0x0008����eax�ĸ�16λ�С�
81 movw %dx,%ax /* selector = 0x0008 = cs */
# ƫ��ֵ�ĵ�16λ����eax�ĵ�16λ�С���ʱeax����
# ����������4�ֽڵ�ֵ��
82 movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
83 # ��ʱedx��������������4�ֽڵ�ֵ��
84 lea _idt,%edi # _idt���ж����������ĵ�ַ��
85 mov $256,%ecx
86 rp_sidt:
87 movl %eax,(%edi) # ��������������������
88 movl %edx,4(%edi) # eax���ݷŵ� edi+4 ��ָ�ڴ�λ�ô���
89 addl $8,%edi # ediָ�������һ�
90 dec %ecx
91 jne rp_sidt
92 lidt idt_descr # �����ж����������Ĵ���ֵ��
93 ret
94
95 /*
96 * setup_gdt
97 *
98 * This routines sets up a new gdt and loads it.
99 * Only two entries are currently built, the same
100 * ones that were built in init.s. The routine
101 * is VERY complicated at two whole lines, so this
102 * rather long comment is certainly needed :-).
103 * This routine will beoverwritten by the page tables.
104 */
/*
* ����ȫ������������ setup_gdt
* ����ӳ�������һ���µ�ȫ����������gdt�������ء���ʱ�����������������ǰ
* ���һ�������ӳ���ֻ�����У����dz��ġ����ӣ����Ե�Ȼ��Ҫ��ô����ע����J��
* ���ӳ���ҳ�����ǵ���
*/
105 setup_gdt:
106 lgdt gdt_descr # ����ȫ�����������Ĵ���(���������úã���234-238��)��
107 ret
108
109 /*
110 * I put the kernel page tables right after the page directory,
111 * using 4 of them to span 16 Mb of physical memory. People with
112 * more than 16MB will have to expand this.
113 */
/* Linus���ں˵��ڴ�ҳ��ֱ�ӷ���ҳĿ¼֮��ʹ����4������Ѱַ16 MB�������ڴ档
* ������ж���16 Mb���ڴ棬����Ҫ��������������ġ�
*/
# ÿ��ҳ����Ϊ4 Kb�ֽڣ�1ҳ�ڴ�ҳ�棩����ÿ��ҳ������Ҫ4���ֽڣ����һ��ҳ�������Դ��
# 1024��������һ��ҳ����Ѱַ4 KB�ĵ�ַ�ռ䣬��һ��ҳ���Ϳ���Ѱַ4 MB�������ڴ档
# ҳ����ĸ�ʽΪ�����ǰ0-11λ���һЩ��־�������Ƿ����ڴ���(Pλ0)����д����(R/Wλ1)��
# ��ͨ�û����dz����û�ʹ��(U/Sλ2)���Ƿ��Ĺ�(�Ƿ�����)(Dλ6)�ȣ������λ12-31��
# ҳ���ַ������ָ��һҳ�ڴ��������ʼ��ַ��
114 .org 0x1000 # ��ƫ��0x1000����ʼ�ǵ�1��ҳ����ƫ��0��ʼ�������ҳ��Ŀ¼����
115 pg0:
116
117 .org 0x2000
118 pg1:
119
120 .org 0x3000
121 pg2:
122
123 .org 0x4000
124 pg3:
125
126 .org 0x5000 # ����������ڴ����ݿ��ƫ��0x5000����ʼ��
127 /*
128 * tmp_floppy_area is used by the floppy-driver when DMA cannot
129 * reach to a buffer-block. It needs to be aligned, so that it isn't
130 * on a 64kB border.
131 */
/* ��DMA��ֱ�Ӵ洢�����ʣ����ܷ��ʻ����ʱ�������tmp_floppy_area�ڴ��
* �Ϳɹ�������������ʹ�á����ַ��Ҫ��������������Ͳ����Խ64KB�߽硣
*/
132 _tmp_floppy_area:
133 .fill 1024,1,0 # ������1024�ÿ��1�ֽڣ������ֵ0��
134
# �����⼸����ջ��������Ϊ��ת��init/main.c�е�main()����������������139����
# ��ָ����ջ��ѹ���˷��ص�ַ������140����ѹ����main()��������ĵ�ַ����head.s
# ����ڵ�218��ִ��retָ��ʱ�ͻᵯ��main()�ĵ�ַ�����ѿ���Ȩת�Ƶ�init/main.c
# �����С��μ���3�����й�C�������û��Ƶ�˵����
# ǰ��3����ջ0ֵӦ�÷ֱ��ʾenvp��argvָ���argc��ֵ����main()û���õ���
# 139�е���ջ������ģ�����main.c����ʱ���Ƚ����ص�ַ��ջ�IJ������������
# main.c��������˳�ʱ���ͻ᷵�ص�����ı��L6������ִ����ȥ��Ҳ����ѭ����
# 140�н�main.c�ĵ�ַѹ���ջ�������������÷�ҳ������setup_paging��������
# ִ��'ret'����ָ��ʱ�ͻὫmain.c����ĵ�ַ������ջ����ȥִ��main.c�����ˡ�
# �й�C�������û�����μ�������˵����
135 after_page_tables:
136 pushl $0 # These are the parameters to main :-)
137 pushl $0 # ��Щ�ǵ���main����IJ�����ָinit/main.c����
138 pushl $0 # ���е�'$'���ű�ʾ����һ��������������
139 pushl $L6 # return address for main, if it decides to.
140 pushl $_main # '_main'�DZ�������main���ڲ���ʾ������
141 jmp setup_paging # ��ת����198�С�
142 L6:
143 jmp L6 # main should never return here, but
144 # just in case, we know what happens.
# main������Բ�Ӧ�÷��ص��������Ϊ���Է���һ��
# ���������˸���䡣�������Ǿ�֪������ʲô�����ˡ�
145
146 /* This is the default interrupt "handler" :-) */
/* ������Ĭ�ϵ��жϡ����������J */
147 int_msg:
148 .asciz "Unknown interrupt\n\r" # �����ַ�����δ֪�ж�(�س�����)����
149 .align 2 # ��4�ֽڷ�ʽ�����ڴ��ַ��
150 ignore_int:
151 pushl %eax
152 pushl %ecx
153 pushl %edx
154 push %ds # ������ע�⣡��ds,es,fs,gs����Ȼ��16λ�ļĴ���������ջ��
155 push %es # ��Ȼ����32λ����ʽ��ջ��Ҳ����Ҫռ��4���ֽڵĶ�ջ�ռ䡣
156 push %fs
157 movl $0x10,%eax # �ö�ѡ�����ʹds,es,fsָ��gdt���е����ݶΣ���
158 mov %ax,%ds
159 mov %ax,%es
160 mov %ax,%fs
161 pushl $int_msg # �ѵ���printk�����IJ���ָ�루��ַ����ջ��ע�⣡��int_msg
162 call _printk # ǰ����'$'�����ʾ��int_msg���Ŵ��ij��֣�'Unkn'����ջJ��
163 popl %eax # �ú�����/kernel/printk.c�С�'_printk'��printk�����ģ����
164 pop %fs # ���ڲ���ʾ����
165 pop %es
166 pop %ds
167 popl %edx
168 popl %ecx
169 popl %eax
170 iret # �жϷ��أ����жϵ���ʱѹ��ջ��CPU��־�Ĵ�����32λ��ֵҲ��������
171
172
173 /*
174 * Setup_paging
175 *
176 * This routine sets up paging by setting the page bit
177 * in cr0. The page tables are set up, identity-mapping
178 * the first 16MB. The pager assumes that no illegal
179 * addresses are produced (ie >4Mb on a 4Mb machine).
180 *
181 * NOTE! Although all physical memory should be identity
182 * mapped by this routine, only the kernel page functions
183 * use the >1Mb addresses directly. All "normal" functions
184 * use just the lower 1Mb, or the local data space, which
185 * will be mapped to some other place - mm keeps track of
186 * that.
187 *
188 * For those with more memory than 16 Mb - tough luck. I've
189 * not got it, why should you :-) The source is here. Change
190 * it. (Seriously - it shouldn't be too difficult. Mostly
191 * change some constants etc. I left it at 16Mb, as my machine
192 * even cannot be extended past that (ok, but it was cheap :-)
193 * I've tried to show which constants to change by having
194 * some kind of marker at them (search for "16Mb"), but I
195 * won't guarantee that's all :-( )
196 */
/*
* ����ӳ���ͨ�����ÿ��ƼĴ���cr0�ı�־��PG λ31�����������ڴ�ķ�ҳ�������ܣ�
* �����ø���ҳ��������ݣ��Ժ��ӳ��ǰ16 MB�������ڴ档��ҳ���ٶ���������Ƿ���
* ��ַӳ�䣨Ҳ����ֻ��4Mb�Ļ��������ó�����4Mb���ڴ��ַ����
*
* ע�⣡�������е�������ַ��Ӧ��������ӳ�����к��ӳ�䣬��ֻ���ں�ҳ�����������
* ֱ��ʹ��>1Mb�ĵ�ַ�����С���ͨ��������ʹ�õ���1Mb�ĵ�ַ�ռ䣬������ʹ�þֲ�����
* �ռ䣬�õ�ַ�ռ佫��ӳ�䵽����һЩ�ط�ȥ -- mm���ڴ�������������Щ�µġ�
*
* ������Щ�ж���16Mb�ڴ�ļһ� �C ����̫�����ˣ��һ�û�У�Ϊʲô�����J���������
* ������������İɡ���ʵ���ϣ��Ⲣ��̫���ѵġ�ͨ��ֻ����һЩ�����ȡ��Ұ�������
* Ϊ16Mb����Ϊ�ҵĻ�������ô�����������ܳ���������ޣ���Ȼ���ҵĻ����Ǻܱ��˵�J����
* ���Ѿ�ͨ������ij���־��������Ҫ�Ķ��ĵط���������16Mb���������Ҳ��ܱ�֤����Щ
* ��������L����
*/
# ����Ӣ��ע�͵�2�εĺ�����ָ�ڻ��������ڴ��д���1MB���ڴ�ռ���Ҫ���������ڴ�����
# ���ڴ����ռ���mmģ����������漰��ҳ��ӳ��������ں�����������������������ָ��һ��
#����ͨ����������Ҫʹ�����ڴ�����ҳ�棬����Ҫʹ��get_free_page()�Ⱥ�����ȡ����Ϊ����
# �������ڴ�ҳ���ǹ�����Դ�������г������ͳһ�����Ա�����Դ���ú;�����
#
# ���ڴ�������ַ0x0����ʼ���1ҳҳĿ¼����4ҳҳ����ҳĿ¼����ϵͳ���н��̹��õģ���
# �����4ҳҳ���������ں�ר�ã�����һһӳ�����Ե�ַ��ʼ16MB�ռ䷶Χ�������ڴ��ϡ�����
# �µĽ��̣�ϵͳ�������ڴ���Ϊ������ҳ����ҳ�������⣬1ҳ�ڴ泤����4096�ֽڡ�
197 .align 2 # ��4�ֽڷ�ʽ�����ڴ��ַ�߽硣
198 setup_paging: # ���ȶ�5ҳ�ڴ棨1ҳĿ¼ + 4ҳҳ�������㡣
199 movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */
200 xorl %eax,%eax
201 xorl %edi,%edi /* pg_dir is at 0x000 */
# ҳĿ¼��0x000��ַ��ʼ��
202 cld;rep;stosl # eax���ݴ浽es:edi��ָ�ڴ�λ�ô�����edi��4��
# ����4������ҳĿ¼���е����Ϊ���ǣ��ںˣ�����4��ҳ������ֻ������4�
# ҳĿ¼��Ľṹ��ҳ������Ľṹһ����4���ֽ�Ϊ1��μ�����113���µ�˵����
# ����"$pg0+7"��ʾ��0x00001007����ҳĿ¼���еĵ�1�
# ���1��ҳ�����ڵĵ�ַ = 0x00001007 & 0xfffff000 = 0x1000��
# ��1��ҳ�������Ա�־ = 0x00001007 & 0x00000fff = 0x07����ʾ��ҳ���ڡ��û��ɶ�д��
203 movl $pg0+7,_pg_dir /* set present bit/user r/w */
204 movl $pg1+7,_pg_dir+4 /* --------- " " --------- */
205 movl $pg2+7,_pg_dir+8 /* --------- " " --------- */
206 movl $pg3+7,_pg_dir+12 /* --------- " " --------- */
# ����6����д4��ҳ��������������ݣ����У�4(ҳ��)*1024(��/ҳ��)=4096��(0 - 0xfff)��
# Ҳ����ӳ�������ڴ� 4096*4Kb = 16Mb��
# ÿ��������ǣ���ǰ����ӳ��������ڴ��ַ + ��ҳ�ı�־�������Ϊ7����
# ʹ�õķ����Ǵ����һ��ҳ�������һ�ʼ������˳����д��һ��ҳ�������һ����ҳ���е�
# λ����1023*4 = 4092��������һҳ�����һ���λ�þ���$pg3+4092��
207 movl $pg3+4092,%edi # edi�����һҳ�����һ�
208 movl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */
# ���1���Ӧ�����ڴ�ҳ��ĵ�ַ��0xfff000��
# �������Ա�־7����Ϊ0xfff007��
209 std # ����λ��λ��ediֵ�ݼ�(4�ֽ�)��
210 1: stosl /* fill pages backwards - more efficient :-) */
211 subl $0x1000,%eax # ÿ��д��һ�������ֵַ��0x1000��
212 jge 1b # ���С��0��˵��ȫ��д���ˡ�
# ����ҳĿ¼����ַ�Ĵ���cr3��ֵ��ָ��ҳĿ¼����cr3�б������ҳĿ¼����������ַ��
213 xorl %eax,%eax /* pg_dir is at 0x0000 */ # ҳĿ¼����0x0000����
214 movl %eax,%cr3 /* cr3 - page directory start */
# ��������ʹ�÷�ҳ������cr0��PG��־��λ31��
215 movl %cr0,%eax
216 orl $0x80000000,%eax # ����PG��־��
217 movl %eax,%cr0 /* set paging (PG) bit */
218 ret /* this also flushes prefetch-queue */
# �ڸı��ҳ������־��Ҫ��ʹ��ת��ָ��ˢ��Ԥȡָ����У������õ��Ƿ���ָ��ret��
# �÷���ָ�����һ�������ǽ�140��ѹ���ջ�е�main����ĵ�ַ����������ת��/init/main.c
# ����ȥ���С������˾����������ˡ�
219
220 .align 2 # ��4�ֽڷ�ʽ�����ڴ��ַ�߽硣
221 .word 0 # �����ȿճ�2�ֽڣ�����224���ϵij�����4�ֽڶ���ġ�
! �����Ǽ����ж����������Ĵ���idtr��ָ��lidtҪ���6�ֽڲ�������ǰ2�ֽ���idt��������
! ��4�ֽ���idt�������Ե�ַ�ռ��е�32λ����ַ��
222 idt_descr:
223 .word 256*8-1 # idt contains 256 entries # ��256���=���� - 1��
224 .long _idt
225 .align 2
226 .word 0
! �������ȫ�����������Ĵ���gdtr��ָ��lgdtҪ���6�ֽڲ�������ǰ2�ֽ���gdt��������
! ��4�ֽ���gdt�������Ի���ַ������ȫ�ֱ���������Ϊ2KB�ֽڣ�0x7ff���ɣ�����Ϊÿ8�ֽ�
! ���һ������������Ա��й�����256�����_gdt��ȫ�ֱ��ڱ������е�ƫ��λ�ã���234�С�
227 gdt_descr:
228 .word 256*8-1 # so does gdt (not that that's any # ע��not �� note
229 .long _gdt # magic number, but it works for me :^)
230
231 .align 3 # ��8��2^3���ֽڷ�ʽ�����ڴ��ַ�߽硣
232 _idt: .fill 256,8,0 # idt is uninitialized # 256�ÿ��8�ֽڣ���0��
233
# ȫ�ֱ���ǰ4��ֱ��ǿ�����ã�������������������ݶ���������ϵͳ���ö�������������
# ϵͳ���ö���������û�����ô���Linus��ʱ���������ϵͳ���ô���ר�ŷ�����������Ķ��С�
# ���滹Ԥ����252��Ŀռ䣬���ڷ�������������ľֲ�������(LDT)�Ͷ�Ӧ������״̬��TSS
# ����������
# (0-nul, 1-cs, 2-ds, 3-syscall, 4-TSS0, 5-LDT0, 6-TSS1, 7-LDT1, 8-TSS2 etc...)
234 _gdt: .quad 0x0000000000000000 /* NULL descriptor */
235 .quad 0x00c09a0000000fff /* 16Mb */ # 0x08���ں˴�������16MB��
236 .quad 0x00c0920000000fff /* 16Mb */ # 0x10���ں����ݶ����16MB��
237 .quad 0x0000000000000000 /* TEMPORARY - don't use */
238 .fill 252,8,0 /* space for LDT's and TSS's etc */ # Ԥ���ռ䡣
1 /*
2 * linux/init/main.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
// ����ꡰ__LIBRARY__����Ϊ�˰���������unistd.h�е���Ƕ���������Ϣ��
7 #define __LIBRARY__
// *.hͷ�ļ����ڵ�Ĭ��Ŀ¼��include/�����ڴ����оͲ�����ȷָ����λ�á��������UNIX��
// ��ͷ�ļ�������Ҫָ�����ڵ�Ŀ¼������˫������ס��unistd.h�DZ����ų����������ļ���
// ���ж����˸��ַ��ų��������ͣ��������˸��ֺ���������������˷���__LIBRARY__����
// ����ϵͳ���úź���Ƕ������syscall0()�ȡ�
8 #include <unistd.h>
9 #include <time.h> // ʱ������ͷ�ļ�����������Ҫ������tm�ṹ��һЩ�й�ʱ��ĺ���ԭ�Ρ�
10
11 /*
12 * we need this inline - forking from kernel space will result
13 * in NO COPY ON WRITE (!!!), until an execve is executed. This
14 * is no problem, but for the stack. This is handled by not letting
15 * main() use the stack at all after fork(). Thus, no function
16 * calls - which means inline code for fork too, as otherwise we
17 * would use the stack upon exit from 'fork()'.
18 *
19 * Actually only pause and fork are needed inline, so that there
20 * won't be any messing with the stack from main(), but we define
21 * some others too.
22 */
/*
* ������Ҫ������Щ��Ƕ��� - ���ں˿ռ䴴�����̽�����û��дʱ����(COPY ON WRITE)!!!
* ֱ��ִ��һ��execve���á���Զ�ջ���ܴ������⡣������������fork()���ú���main()
* ʹ���κζ�ջ����˾Ͳ����к������� - ����ζ��forkҲҪʹ����Ƕ�Ĵ��룬���������ڴ�
* fork()�˳�ʱ��Ҫʹ�ö�ջ�ˡ�
*
* ʵ����ֻ��pause��fork��Ҫʹ����Ƕ��ʽ���Ա�֤��main()�в���Ū�Ҷ�ջ����������ͬ
* ʱ������������һЩ������
*/
// Linux���ں˿ռ䴴������ʱ��ʹ��дʱ���Ƽ�����Copy on write����main()���ƶ����û�
// ģʽ��������0����ִ����Ƕ��ʽ��fork()��pause()����˿ɱ�֤��ʹ������0���û�ջ��
// ��ִ��moveto_user_mode()֮������main()��������0�������������ˡ�������0����
// �н������ӽ��̵ĸ����̡���������һ���ӽ���ʱ��init���̣�����������1���������ں�
// �ռ䣬���û��ʹ��дʱ���ƹ��ܡ���ʱ����0���û�ջ��������1���û�ջ�������ǹ�ͬ
// ʹ��һ��ջ�ռ䡣���ϣ����main.c����������0�Ļ�����ʱ��Ҫ�жԶ�ջ���κβ�������
// ��Ū�Ҷ�ջ�������ٴ�ִ��fork()��ִ�й�execve()���������س����Ѳ������ں˿ռ䣬
// ��˿���ʹ��дʱ���Ƽ����ˡ���μ�5.3�ڡ�Linux�ں�ʹ���ڴ�ķ��������ݡ�
// ����_syscall0()��unistd.h�е���Ƕ����롣��Ƕ�������ʽ����Linux��ϵͳ�����ж�
// 0x80�����ж�������ϵͳ���õ���ڡ��������ʵ������int fork()��������ϵͳ���á���չ
// ����֮�ͻ��������ס�syscall0����������0��ʾ������1��ʾ1��������
// �μ�include/unistd.h��133�С�
23 static inline _syscall0(int,fork)
// int pause()ϵͳ���ã���ͣ���̵�ִ�У�ֱ���յ�һ���źš�
24 static inline _syscall0(int,pause)
// int setup(void * BIOS)ϵͳ���ã�������linux��ʼ����������������б����ã���
25 static inline _syscall1(int,setup,void *,BIOS)
// int sync()ϵͳ���ã������ļ�ϵͳ��
26 static inline _syscall0(int,sync)
27
28 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
29 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct����1����ʼ����
// �����ݡ�����һЩ�Ժ����ʽ������й��������������úͻ�ȡ��
// Ƕ��ʽ��ຯ������
30 #include <linux/head.h> // headͷ�ļ��������˶��������ļṹ���ͼ���ѡ���������
31 #include <asm/system.h> // ϵͳͷ�ļ����Ժ���ʽ�����������й����û���������/�ж���
// �ȵ�Ƕ��ʽ����ӳ���
32 #include <asm/io.h> // ioͷ�ļ����Ժ��Ƕ���������ʽ�����io�˿ڲ����ĺ�����
33
34 #include <stddef.h> // ������ͷ�ļ���������NULL, offsetof(TYPE, MEMBER)��
35 #include <stdarg.h> // ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��
// ����(va_list)��������(va_start, va_arg��va_end)��vsprintf��
// vprintf��vfprintf��
36 #include <unistd.h>
37 #include <fcntl.h> // �ļ�����ͷ�ļ��������ļ������������IJ������Ƴ������ŵĶ��塣
38 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
39
40 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file,buffer_head,m_inode�ȣ���
41 // �����ж��壺extern int ROOT_DEV��
42 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ڴ���ַ���������Ƕ�뺯����
43
44 static char printbuf[1024]; // ��̬�ַ������飬�����ں���ʾ��Ϣ�Ļ��档
45
46 extern char *strcpy();
47 extern int vsprintf(); // ��ʽ�������һ�ַ����У�vsprintf.c��92�У���
48 extern void init(void); // ����ԭ�Σ���ʼ����������168�У���
49 extern void blk_dev_init(void); // ���豸��ʼ���ӳ���blk_drv/ll_rw_blk.c,157�У�
50 extern void chr_dev_init(void); // �ַ��豸��ʼ����chr_drv/tty_io.c, 347�У�
51 extern void hd_init(void); // Ӳ�̳�ʼ������blk_drv/hd.c, 343�У�
52 extern void floppy_init(void); // ������ʼ������blk_drv/floppy.c, 457�У�
53 extern void mem_init(long start, long end); // �ڴ������ʼ����mm/memory.c, 399�У�
54 extern long rd_init(long mem_start, int length); // �����̳�ʼ��(blk_drv/ramdisk.c,52)
55 extern long kernel_mktime(struct tm * tm); // ����ϵͳ��������ʱ�䣨�룩��
56
// �ں�ר��sprintf()�������ú������ڲ�����ʽ����Ϣ�������ָ��������str�С�����'*fmt'
// ָ����������õĸ�ʽ���μ���C�����鼮�����ӳ���������vsprintf���ʹ�õ�һ����
// ���ӡ�����ʹ��vsprintf()����ʽ���ַ�������str���������μ���179���ϵ�printf()������
57 static int sprintf(char * str, const char *fmt, ...)
58 {
59 va_list args;
60 int i;
61
62 va_start(args, fmt);
63 i = vsprintf(str, fmt, args);
64 va_end(args);
65 return i;
66 }
67
68 /*
69 * This is set up by the setup-routine at boot-time
70 */
/*
* ������Щ���������ں������ڼ���setup.s�������õġ�
*/
// �������зֱ�ָ�������Ե�ַǿ��ת��Ϊ�����������͵�ָ�룬����ȡָ����ָ���ݡ�����
// �ں˴���α�ӳ�䵽��������ַ�㿪ʼ�ĵط��������Щ���Ե�ַ����Ҳ�Ƕ�Ӧ��������ַ��
// ��Щָ����ַ���ڴ�ֵ�ĺ�����μ���6�µı�6-2��setup�����ȡ������IJ�������
// drive_info�ṹ��μ������125�С�
71 #define EXT_MEM_K (*(unsigned short *)0x90002) // 1MB�Ժ����չ�ڴ��С��KB����
72 #define CON_ROWS ((*(unsigned short *)0x9000e) & 0xff) // ѡ���Ŀ���̨��Ļ�С�������
73 #define CON_COLS (((*(unsigned short *)0x9000e) & 0xff00) >> 8)
74 #define DRIVE_INFO (*(struct drive_info *)0x90080) // Ӳ�̲�����32�ֽ����ݡ�
75 #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) // ���ļ�ϵͳ�����豸�š�
76 #define ORIG_SWAP_DEV (*(unsigned short *)0x901FA) // �����ļ������豸�š�
77
78 /*
79 * Yeah, yeah, it's ugly, but I cannot find how to do this correctly
80 * and this seems to work. I anybody has more info on the real-time
81 * clock I'd be interested. Most of this was trial and error, and some
82 * bios-listing reading. Urghh.
83 */
/*
* �ǰ����ǰ���������γ���ܲ�����Ҳ�֪�������ȷ��ʵ�֣����Һ���
* ���������С�����й���ʵʱʱ�Ӹ�������ϣ����Һܸ���Ȥ����Щ������
* ̽�����ģ��������һЩbios���ǣ�
*/
84
// ��κ��ȡCMOSʵʱʱ����Ϣ��outb_p��inb_p��include/asm/io.h�ж���Ķ˿���������ꡣ
85 #define CMOS_READ(addr) ({ \
86 outb_p(0x80|addr,0x70); \ // 0x70��д��ַ�˿ںţ�0x80|addr��Ҫ��ȡ��CMOS�ڴ��ַ��
87 inb_p(0x71); \ // 0x71�Ƕ����ݶ˿ںš�
88 })
89
// ����ꡣ��BCD��ת���ɶ�������ֵ��BCD�����ð���ֽڣ�4���أ���ʾһ��10�����������
// һ���ֽڱ�ʾ2��10��������(val)&15ȡBCD��ʾ��10���Ƹ�λ������ (val)>>4ȡBCD��ʾ
// ��10����ʮλ�����ٳ���10��������������Ӿ���һ���ֽ�BCD���ʵ�ʶ�������ֵ��
90 #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
91
// �ú���ȡCMOSʵʱ����Ϣ��Ϊ����ʱ�䣬�����浽ȫ�ֱ���startup_time(��)�С��μ�����
// CMOS�ڴ��б�˵�������е��õĺ���kernel_mktime()���ڼ����1970��1��1��0ʱ��
// �������վ�������������Ϊ����ʱ�䣨kernel/mktime.c 41�У���
92 static void time_init(void)
93 {
94 struct tm time; // ʱ��ṹtm������include/time.h�С�
95
// CMOS�ķ����ٶȺ�����Ϊ�˼�Сʱ�����ڶ�ȡ������ѭ����������ֵ������ʱCMOS��
// ��ֵ�����˱仯����ô�����¶�ȡ����ֵ�������ں˾��ܰ���CMOSʱ����������1��֮�ڡ�
96 do {
97 time.tm_sec = CMOS_READ(0); // ��ǰʱ����ֵ������BCD��ֵ����
98 time.tm_min = CMOS_READ(2); // ��ǰ����ֵ��
99 time.tm_hour = CMOS_READ(4); // ��ǰСʱֵ��
100 time.tm_mday = CMOS_READ(7); // һ���еĵ������ڡ�
101 time.tm_mon = CMOS_READ(8); // ��ǰ�·ݣ�1��12����
102 time.tm_year = CMOS_READ(9); // ��ǰ��ݡ�
103 } while (time.tm_sec != CMOS_READ(0));
104 BCD_TO_BIN(time.tm_sec); // ת���ɶ�������ֵ��
105 BCD_TO_BIN(time.tm_min);
106 BCD_TO_BIN(time.tm_hour);
107 BCD_TO_BIN(time.tm_mday);
108 BCD_TO_BIN(time.tm_mon);
109 BCD_TO_BIN(time.tm_year);
110 time.tm_mon--; // tm_mon���·ݷ�Χ��0��11��
111 startup_time = kernel_mktime(&time); // ���㿪��ʱ�䡣kernel/mktime.c 41�С�
112 }
113
// ���涨��һЩ�ֲ�������
114 static long memory_end = 0; // �������е������ڴ��������ֽ�������
115 static long buffer_memory_end = 0; // ���ٻ�����ĩ�˵�ַ��
116 static long main_memory_start = 0; // ���ڴ棨�����ڷ�ҳ����ʼ��λ�á�
117 static char term[32]; // �ն������ַ�����������������
118
// ��ȡ��ִ��/etc/rc�ļ�ʱ��ʹ�õ������в����ͻ���������
119 static char * argv_rc[] = { "/bin/sh", NULL }; // ����ִ�г���ʱ�������ַ������顣
120 static char * envp_rc[] = { "HOME=/", NULL ,NULL }; // ����ִ�г���ʱ�Ļ����ַ������顣
121
// ���е�¼shellʱ��ʹ�õ������в����ͻ���������
// ��122����argv[0]�е��ַ���-���Ǵ��ݸ�shell����sh��һ����־��ͨ��ʶ��ñ�־��
// sh�������Ϊ��¼shellִ�С���ִ�й�������shell��ʾ����ִ��sh��һ����
122 static char * argv[] = { "-/bin/sh",NULL }; // ͬ�ϡ�
123 static char * envp[] = { "HOME=/usr/root", NULL, NULL };
124
125 struct drive_info { char dummy[32]; } drive_info; // ���ڴ��Ӳ�̲�������Ϣ��
126
// �ں˳�ʼ��������ʼ��������������0��idle�����������������С�
// Ӣ��ע�ͺ����ǡ�����ȷʵ��void��û������startup����(head.s)�о�����������ġ����μ�
// head.s�����136�п�ʼ�ļ��д��롣
127 void main(void) /* This really IS void, no error here. */
128 { /* The startup routine assumes (well, ...) this */
129 /*
130 * Interrupts are still disabled. Do necessary setups, then
131 * enable them
132 */
/*
* ��ʱ�ж��Ա���ֹ�ţ������Ҫ�����ú�ͽ��俪����
*/
// ���ȱ�����ļ�ϵͳ�豸�źͽ����ļ��豸�ţ�������setup.s�����л�ȡ����Ϣ���ÿ���̨
// �ն���Ļ�С�������������TERM�����������ó�ʼinit������ִ��etc/rc�ļ���shell����
// ʹ�õĻ����������Լ������ڴ�0x90080����Ӳ�̲�������
// ����ROOT_DEV ����ǰ���������include/linux/fs.h�ļ���206���ϱ�����Ϊextern int��
// ��SWAP_DEV��include/linux/mm.h�ļ���Ҳ������ͬ����������mm.h�ļ���û����ʽ������
// ������ǰ������Ϊǰ���������include/linux/sched.h�ļ����Ѿ���������
133 ROOT_DEV = ORIG_ROOT_DEV; // ROOT_DEV������fs/super.c��29��
134 SWAP_DEV = ORIG_SWAP_DEV; // SWAP_DEV������mm/swap.c��36��
135 sprintf(term, "TERM=con%dx%d", CON_COLS, CON_ROWS);
136 envp[1] = term;
137 envp_rc[1] = term;
138 drive_info = DRIVE_INFO; // �����ڴ�0x90080����Ӳ�̲�������
// ���Ÿ��ݻ��������ڴ��������ø��ٻ����������ڴ�����λ�úͷ�Χ��
// ���ٻ���ĩ�˵�ַ��buffer_memory_end�������ڴ�������memory_end��
// ���ڴ濪ʼ��ַ ��main_memory_start��
139 memory_end = (1<<20) + (EXT_MEM_K<<10); // �ڴ��С=1Mb + ��չ�ڴ�(k)*1024�ֽڡ�
140 memory_end &= 0xfffff000; // ���Բ���4Kb��1ҳ�����ڴ�����
141 if (memory_end > 16*1024*1024) // ����ڴ�������16Mb����16Mb�ơ�
142 memory_end = 16*1024*1024;
143 if (memory_end > 12*1024*1024) // ����ڴ�>12Mb�������û�����ĩ��=4Mb
144 buffer_memory_end = 4*1024*1024;
145 else if (memory_end > 6*1024*1024) // �������ڴ�>6Mb�������û�����ĩ��=2Mb
146 buffer_memory_end = 2*1024*1024;
147 else
148 buffer_memory_end = 1*1024*1024; // ���������û�����ĩ��=1Mb
149 main_memory_start = buffer_memory_end; // ���ڴ���ʼλ�� = ������ĩ�ˡ�
// �����Makefile�ļ��ж������ڴ������̷���RAMDISK�����ʼ�������̡���ʱ���ڴ潫���١�
//�μ�kernel/blk_drv/ramdisk.c��
150 #ifdef RAMDISK
151 main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
152 #endif
// �������ں˽������з���ij�ʼ���������Ķ�ʱ��ø��ŵ��õij��������ȥ������ʵ�ڿ�
// ����ȥ�ˣ����ȷ�һ�ţ���������һ����ʼ������ -- ���Ǿ���̸֮J��
153 mem_init(main_memory_start,memory_end); // ���ڴ�����ʼ������mm/memory.c��399��
154 trap_init(); // �����ţ�Ӳ���ж���������ʼ������kernel/traps.c��181��
155 blk_dev_init(); // ���豸��ʼ���� ��blk_drv/ll_rw_blk.c��157��
156 chr_dev_init(); // �ַ��豸��ʼ���� ��chr_drv/tty_io.c��347��
157 tty_init(); // tty��ʼ���� ��chr_drv/tty_io.c��406��
158 time_init(); // ���ÿ�������ʱ�䡣������92�У�
159 sched_init(); // ���ȳ����ʼ������������0��tr,ldtr����kernel/sched.c��385��
160 buffer_init(buffer_memory_end); // ���������ʼ�������ڴ������ȡ���fs/buffer.c��348��
161 hd_init(); // Ӳ�̳�ʼ���� ��blk_drv/hd.c��343��
162 floppy_init(); // ������ʼ���� ��blk_drv/floppy.c��457��
163 sti(); // ���г�ʼ�������������ˣ����ǿ����жϡ�
// �������ͨ���ڶ�ջ�����õIJ����������жϷ���ָ����������0ִ�С�
164 move_to_user_mode(); // �Ƶ��û�ģʽ��ִ�С���include/asm/system.h����1�У�
165 if (!fork()) { /* we count on this going ok */
166 init(); // ���½����ӽ��̣�����1��init���̣���ִ�С�
167 }
// ������뿪ʼ������0���������С�
168 /*
169 * NOTE!! For any other task 'pause()' would mean we have to get a
170 * signal to awaken, but task0 is the sole exception (see 'schedule()')
171 * as task 0 gets activated at every idle moment (when no other tasks
172 * can run). For task0 'pause()' just means we go check if some other
173 * task can run, and if not we return here.
174 */
/* ע��!! �����κ�����������'pause()'����ζ�����DZ���ȴ��յ�һ���ź�
* �Ż᷵�ؾ���̬��������0��task0����Ψһ����������μ�'schedule()'����
* ��Ϊ����0���κο���ʱ���ﶼ�ᱻ�����û����������������ʱ�������
* ��������0'pause()'����ζ�����Ƿ������鿴�Ƿ�����������������У����
* û�еĻ����Ǿͻص����һֱѭ��ִ��'pause()'��
*/
// pause()ϵͳ���ã�kernel/sched.c,144���������0ת���ɿ��жϵȴ�״̬����ִ�е��Ⱥ�����
// ���ǵ��Ⱥ���ֻҪ����ϵͳ��û�����������������ʱ�ͻ��л�������0����������������0��
// ״̬��
175 for(;;)
176 __asm__("int $0x80"::"a" (__NR_pause):"ax"); // ��ִ��ϵͳ����pause()��
177 }
178
// ���溯��������ʽ����Ϣ�������������豸stdout(1)��������ָ��Ļ����ʾ������'*fmt'
// ָ����������õĸ�ʽ���μ���C�����鼮�����ӳ���������vsprintf���ʹ�õ�һ����
// ���ӡ��ó���ʹ��vsprintf()����ʽ�����ַ�������printbuf��������Ȼ����write()������
// ����������������豸��1--stdout����vsprintf()������ʵ�ּ�kernel/vsprintf.c��
179 static int printf(const char *fmt, ...)
180 {
181 va_list args;
182 int i;
183
184 va_start(args, fmt);
185 write(1,printbuf,i=vsprintf(printbuf, fmt, args));
186 va_end(args);
187 return i;
188 }
189
// ��main()���Ѿ�������ϵͳ��ʼ���������ڴ����������Ӳ���豸����������init()����
// ����������0��1�δ������ӽ��̣�����1���С������ȶԵ�һ����Ҫִ�еij���shell��
// �Ļ������г�ʼ����Ȼ���Ե�¼shell��ʽ���ظó���ִ��֮��
190 void init(void)
191 {
192 int pid,i;
193
// setup() ��һ��ϵͳ���á����ڶ�ȡӲ�̲���������������Ϣ�����������̣������ڵĻ�����
// ��װ���ļ�ϵͳ�豸���ú�����25���ϵĺ궨�壬��Ӧ������sys_setup()���ڿ��豸��Ŀ¼
// kernel/blk_drv/hd.c��74��
194 setup((void *) &drive_info);
// �����Զ�д���ʷ�ʽ���豸��/dev/tty0��������Ӧ�ն˿���̨���������ǵ�һ�δ��ļ�
// ��������˲������ļ�����ţ��ļ����������϶���0���þ����UNIX�����ϵͳĬ�ϵĿ�
// ��̨��������stdin�������ٰ����Զ���д�ķ�ʽ�ֱ����Ϊ�˸��Ʋ����������д��
// ���stdout�ͱ�����������stderr������ǰ��ġ�(void)��ǰ���ڱ�ʾǿ�ƺ�������
// ����ֵ��
195 (void) open("/dev/tty1",O_RDWR,0);
196 (void) dup(0); // ���ƾ�����������1��--stdout������豸��
197 (void) dup(0); // ���ƾ�����������2��--stderr����������豸��
// �����ӡ���������������ֽ�����ÿ��1024�ֽڣ��Լ����ڴ��������ڴ��ֽ�����
198 printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS,
199 NR_BUFFERS*BLOCK_SIZE);
200 printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);
// ����fork()���ڴ���һ���ӽ��̣�����2�������ڱ��������ӽ��̣�fork()������0ֵ������
// ԭ���̣������̣����ӽ��̵Ľ��̺�pid�����Ե�202--206�����ӽ���ִ�е����ݡ�����
// ���̹ر��˾��0��stdin������ֻ����ʽ��/etc/rc�ļ�����ʹ��execve()��������������
// �滻�� /bin/sh����shell����Ȼ��ִ�� /bin/sh������Я���IJ����ͻ���������
// ����argv_rc��envp_rc����������رվ��0�����̴� /etc/rc�ļ��������ǰѱ�����
// stdin�ض��� /etc/rc�ļ�������shell����/bin/sh�Ϳ�������rc�ļ������õ������
// ������sh�����з�ʽ�Ƿǽ���ʽ�ģ������ִ����rc�ļ��е������ͻ������˳�������2
// Ҳ��֮����������execve()����˵����μ�fs/exec.c����207�С�
// ����_exit()�˳�ʱ�ij�����1 �C ����δ���ɣ�2 -- �ļ���Ŀ¼�����ڡ�
201 if (!(pid=fork())) {
202 close(0);
203 if (open("/etc/rc",O_RDONLY,0))
204 _exit(1); // �����ļ�ʧ�ܣ����˳�(lib/_exit.c,10)��
205 execve("/bin/sh",argv_rc,envp_rc); // �滻��/bin/sh����ִ�С�
206 _exit(2); // ��execve()ִ��ʧ�����˳���
207 }
// ���滹�Ǹ����̣�1��ִ�е���䡣wait()�ȴ��ӽ���ֹͣ����ֹ������ֵӦ���ӽ��̵Ľ��̺�
// (pid)��������������Ǹ����̵ȴ��ӽ��̵Ľ�����&i�Ǵ�ŷ���״̬��Ϣ��λ�á����wait()
// ����ֵ�������ӽ��̺ţ�������ȴ���
208 if (pid>0)
209 while (pid != wait(&i))
210 /* nothing */; /* ��ѭ�� */
// ���ִ�е����˵���մ������ӽ��̵�ִ����ֹͣ����ֹ�ˡ�����ѭ���������ٴ���һ����
// ���̣��������������ʾ����ʼ�������ӽ���ʧ�ܡ���Ϣ������ִ�С��������������ӽ�
// �̽��ر�������ǰ�������ľ��(stdin, stdout, stderr)���´���һ���Ự�����ý�����ţ�
// Ȼ�����´� /dev/tty0 ��Ϊ stdin�������Ƴ� stdout�� stderr���ٴ�ִ��ϵͳ���ͳ���
// /bin/sh�������ִ����ѡ�õIJ����ͻ���������ѡ��һ�ף�������122--123�У���Ȼ��
// ���ٴ����� wait()�ȴ�������ӽ�����ֹͣ��ִ�У����ڱ��������ʾ������Ϣ���ӽ���
// pidֹͣ�����У���������i����Ȼ�����������ȥ�����γɡ�����ѭ����
211 while (1) {
212 if ((pid=fork())<0) {
213 printf("Fork failed in init\r\n");
214 continue;
215 }
216 if (!pid) { // �µ��ӽ��̡�
217 close(0);close(1);close(2);
218 setsid(); // ����һ�µĻỰ�ڣ�������˵����
219 (void) open("/dev/tty1",O_RDWR,0);
220 (void) dup(0);
221 (void) dup(0);
222 _exit(execve("/bin/sh",argv,envp));
223 }
224 while (1)
225 if (pid == wait(&i))
226 break;
227 printf("\n\rchild %d died with code %04x\n\r",pid,i);
228 sync(); // ͬ��������ˢ�»�������
229 }
230 _exit(0); /* NOTE! _exit, not exit() */ /*ע�⣡��_exit()����exit()*/
// _exit()��exit()������������ֹһ����������_exit()ֱ����һ��sys_exitϵͳ���ã���
// exit()��ͨ������ͨ�������е�һ��������������ִ��һЩ����������������ִ�и���ֹ
// �������ر����б�IO�ȣ�Ȼ�����sys_exit��
231 }
232
1 /*
2 * linux/kernel/asm.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * asm.s contains the low-level code for most hardware faults.
9 * page_exception is handled by the mm, so that isn't here. This
10 * file also handles (hopefully) fpu-exceptions due to TS-bit, as
11 * the fpu must be properly saved/resored. This hasn't been tested.
12 */
/*
* asm.s�����а����ֵ�Ӳ�����ϣ�������������ĵײ�δ��롣ҳ�쳣���ڴ��������
* mm���������Բ�������˳�������ϣ��������������TS-λ����ɵ�fpu�쳣����Ϊ
* fpu������ȷ�ؽ��б���/�ָ���������Щ��û�в��Թ���
*/
13
# �������ļ���Ҫ�漰��Intel�����ж�int0--int16�Ĵ�����int17-int31�������ʹ�ã���
# ������һЩȫ�ֺ���������������ԭ����traps.c��˵����
14 .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
15 .globl _double_fault,_coprocessor_segment_overrun
16 .globl _invalid_TSS,_segment_not_present,_stack_segment
17 .globl _general_protection,_coprocessor_error,_irq13,_reserved
18 .globl _alignment_check
19
# ������γ����������ŵ������
# int0 -- �������������������� ���ͣ��������ţ��ޡ�
# ��ִ��DIV��IDIVָ��ʱ����������0��CPU�ͻ��������쳣����EAX����AX��AL������
# ����һ���Ϸ��������Ľ��ʱ��Ҳ���������쳣��21�б��'_do_divide_error'ʵ������
# C���Ժ���do_divide_error()�����������ģ���ж�Ӧ�����ơ�����'do_divide_error'��
# traps.c��ʵ�֣���101�п�ʼ����
20 _divide_error:
21 pushl $_do_divide_error # ���Ȱѽ�Ҫ���õĺ�����ַ��ջ��
22 no_error_code: # �����������Ŵ�������ڴ����������56�еȡ�
23 xchgl %eax,(%esp) # _do_divide_error�ĵ�ַ �� eax��eax��������ջ��
24 pushl %ebx
25 pushl %ecx
26 pushl %edx
27 pushl %edi
28 pushl %esi
29 pushl %ebp
30 push %ds # ����16λ�ĶμĴ�����ջ��ҲҪռ��4���ֽڡ�
31 push %es
32 push %fs
33 pushl $0 # "error code" # ����ֵ0��Ϊ��������ջ��
34 lea 44(%esp),%edx # ȡ��Ч��ַ����ջ��ԭ���÷��ص�ַ����ջָ��λ�ã�
35 pushl %edx # ��ѹ���ջ��
36 movl $0x10,%edx # ��ʼ���μĴ���ds��es��fs�������ں����ݶ�ѡ�����
37 mov %dx,%ds
38 mov %dx,%es
39 mov %dx,%fs
# �����ϵ�'*'�ű�ʾ���ò�����ָ����ַ���ĺ�������Ϊ��ӵ��á����ĺ����ǵ������𱾴�
# �쳣��C��������������do_divide_error()�ȡ���41���ǽ���ջָ���8�൱��ִ������pop
# ������������������������ջ������C����������33�к�35����ջ��ֵ�����ö�ջָ������
# ָ��Ĵ���fs��ջ����
40 call *%eax
41 addl $8,%esp
42 pop %fs
43 pop %es
44 pop %ds
45 popl %ebp
46 popl %esi
47 popl %edi
48 popl %edx
49 popl %ecx
50 popl %ebx
51 popl %eax # ����ԭ��eax�е����ݡ�
52 iret
53
# int1 -- debug�����ж���ڵ㡣��������ͬ�ϡ����ͣ�����/���壨Fault/Trap��������š�
# ��eflags��TF��־��λʱ���������жϡ�������Ӳ���ϵ㣨���ݣ����壬���룺��������
# ������ָ�����������������壬���ߵ��ԼĴ���������Ч������CPU�ͻ�������쳣��
54 _debug:
55 pushl $_do_int3 # _do_debug # C����ָ����ջ������ͬ��
56 jmp no_error_code
57
# int2 -- �������жϵ�����ڵ㡣 ���ͣ����壻����š�
# ���ǽ��еı�����̶��ж�������Ӳ���жϡ�ÿ�����յ�һ��NMI�źţ�CPU�ڲ��ͻ�����ж�
# ����2����ִ�б��ж�Ӧ�����ڣ���˺ܽ�ʡʱ�䡣NMIͨ������Ϊ��Ϊ��Ҫ��Ӳ���¼�ʹ�á�
# ��CPU�յ�һ�� NMI �źŲ��ҿ�ʼִ�����жϴ�������ʱ��������е�Ӳ���ж϶��������ԡ�
58 _nmi:
59 pushl $_do_nmi
60 jmp no_error_code
61
# int3 -- �ϵ�ָ�������жϵ���ڵ㡣 ���ͣ����壻����š�
# ��int 3 ָ���������жϣ���Ӳ���ж��ء���ָ��ͨ���ɵ�ʽ�����뱻��ʽ����Ĵ����С�
# ��������ͬ_debug��
62 _int3:
63 pushl $_do_int3
64 jmp no_error_code
65
# int4 -- ������������ж���ڵ㡣 ���ͣ����壻����š�
# EFLAGS��OF��־��λʱCPUִ��INTOָ��ͻ��������жϡ�ͨ�����ڱ����������������������
66 _overflow:
67 pushl $_do_overflow
68 jmp no_error_code
69
# int5 -- �߽�������ж���ڵ㡣 ���ͣ���������š�
# ������������Ч��Χ����ʱ�������жϡ���BOUNDָ�����ʧ�ܾͻ�������жϡ�BOUNDָ����
# 3���������������1��������������֮�䣬�Ͳ����쳣5��
70 _bounds:
71 pushl $_do_bounds
72 jmp no_error_code
73
# int6 -- ��Ч����ָ������ж���ڵ㡣 ���ͣ���������š�
# CPU ִ�л�����һ����Ч�IJ������������жϡ�
74 _invalid_op:
75 pushl $_do_invalid_op
76 jmp no_error_code
77
# int9 -- Э�������γ��������ж���ڵ㡣 ���ͣ�����������š�
# ���쳣�����ϵ�ͬ��Э������������������Ϊ�ڸ���ָ�������̫��ʱ�����Ǿ������������
# ���ػ泬�����ݶεĸ���ֵ��
78 _coprocessor_segment_overrun:
79 pushl $_do_coprocessor_segment_overrun
80 jmp no_error_code
81
# int15 �C ����Intel�����жϵ���ڵ㡣
82 _reserved:
83 pushl $_do_reserved
84 jmp no_error_code
85
# int45 -- (0x20 + 13) Linux���õ���ѧЭ������Ӳ���жϡ�
# ��Э������ִ����һ������ʱ�ͻᷢ��IRQ13�ж��źţ���֪ͨCPU������ɡ�80387��ִ��
# ����ʱ��CPU��ȴ��������ɡ�����89����0xF0��Э�����˿ڣ�������æ��������ͨ��д
# �ö˿ڣ����жϽ�����CPU��BUSY�����źţ������¼���80387�Ĵ�������չ��������PEREQ��
# �ò�����Ҫ��Ϊ��ȷ���ڼ���ִ��80387���κ�ָ��֮ǰ��CPU��Ӧ���жϡ�
86 _irq13:
87 pushl %eax
88 xorb %al,%al
89 outb %al,$0xF0
90 movb $0x20,%al
91 outb %al,$0x20 # ��8259���жϿ���оƬ����EOI���жϽ������źš�
92 jmp 1f # ��������תָ������ʱ���á�
93 1: jmp 1f
94 1: outb %al,$0xA0 # ����8259���жϿ���оƬ����EOI���жϽ������źš�
95 popl %eax
96 jmp _coprocessor_error # �ú���ԭ�ڱ������У����ѷŵ�system_call.s�С�
97
# �����ж��ڵ���ʱCPU�����жϷ��ص�ַ֮������ѹ���ջ����˷���ʱҲ��Ҫ��������
# �������μ�ͼ5.3(b)����
# int8 -- ˫�������ϡ� ���ͣ��������д����롣
# ͨ����CPU�ڵ���ǰһ���쳣�Ĵ���������ּ�һ���µ��쳣ʱ���������쳣�ᱻ���еؽ���
# ��������Ҳ���������ٵ������CPU���ܽ��������Ĵ��д�����������ʱ�ͻ��������жϡ�
98 _double_fault:
99 pushl $_do_double_fault # C������ַ��ջ��
100 error_code:
101 xchgl %eax,4(%esp) # error code <-> %eax��eaxԭ����ֵ�������ڶ�ջ�ϡ�
102 xchgl %ebx,(%esp) # &function <-> %ebx��ebxԭ����ֵ�������ڶ�ջ�ϡ�
103 pushl %ecx
104 pushl %edx
105 pushl %edi
106 pushl %esi
107 pushl %ebp
108 push %ds
109 push %es
110 push %fs
111 pushl %eax # error code # ��������ջ��
112 lea 44(%esp),%eax # offset # ���ص�ַ����ջָ��λ��ֵ��ջ��
113 pushl %eax
114 movl $0x10,%eax # ���ں����ݶ�ѡ�����
115 mov %ax,%ds
116 mov %ax,%es
117 mov %ax,%fs
118 call *%ebx # ��ӵ��ã�������Ӧ��C���������������ջ��
119 addl $8,%esp # ������ջ��2������C�����IJ�����
120 pop %fs
121 pop %es
122 pop %ds
123 popl %ebp
124 popl %esi
125 popl %edi
126 popl %edx
127 popl %ecx
128 popl %ebx
129 popl %eax
130 iret
131
# int10 -- ��Ч������״̬��(TSS)�� ���ͣ������г����롣
# CPU��ͼ�л���һ�����̣����ý��̵�TSS��Ч������TSS����һ�����������쳣��������TSS
# ���ȳ���104�ֽ�ʱ������쳣�ڵ�ǰ�����в���������л�����ֹ������������ᵼ�����л�
# ����������в������쳣��
132 _invalid_TSS:
133 pushl $_do_invalid_TSS
134 jmp error_code
135
# int11 -- �β����ڡ� ���ͣ������г����롣
# �����õĶβ����ڴ��С����������б�־ָ���β����ڴ��С�
136 _segment_not_present:
137 pushl $_do_segment_not_present
138 jmp error_code
139
# int12 -- ��ջ�δ��� ���ͣ������г����롣
# ָ�������ͼ������ջ�η�Χ�����߶�ջ�β����ڴ��С������쳣11��13����������Щ����
# ϵͳ������������쳣��ȷ��ʲôʱ��Ӧ��Ϊ�����������ջ�ռ䡣
140 _stack_segment:
141 pushl $_do_stack_segment
142 jmp error_code
143
# int13 -- һ�㱣���Գ����� ���ͣ������г����롣
# �����Dz������κ�������Ĵ�����һ���쳣����ʱû�ж�Ӧ�Ĵ���������0--16����ͨ����
# ��鵽���ࡣ
144 _general_protection:
145 pushl $_do_general_protection
146 jmp error_code
147
# int17 -- �߽�����������
# ���������ڴ�߽���ʱ������Ȩ��3���û��������ݷDZ߽����ʱ��������쳣��
148 _alignment_check:
149 pushl $_do_alignment_check
150 jmp error_code
151
# int7 -- �豸�����ڣ�_device_not_available����kernel/sys_call.s��158�С�
# int14 -- ҳ����_page_fault����mm/page.s��14�С�
# int16 -- ����������_coprocessor_error����kernel/sys_call.s��140��
# ʱ���ж�int 0x20��_timer_interrupt����kernel/sys_call.s��189�С�
# ϵͳ����int 0x80��_system_call����kernel/sys_call.s��84�С�
1 /*
2 * linux/kernel/traps.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'Traps.c' handles hardware traps and faults after we have saved some
9 * state in 'asm.s'. Currently mostly a debugging-aid, will be extended
10 * to mainly kill the offending process (probably by giving it a signal,
11 * but possibly by killing it outright if necessary).
12 */
/*
* �ڳ���asm.s�б�����һЩ״̬��������������Ӳ��������ϡ�Ŀǰ��Ҫ���ڵ���Ŀ�ģ�
* �Ժ���չ����ɱ�����Ľ��̣���Ҫ��ͨ������һ���źţ��������ҪҲ��ֱ��ɱ������
*/
13 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ڴ���ַ���������Ƕ�뺯����
14
15 #include <linux/head.h> // headͷ�ļ��������˶��������ļṹ���ͼ���ѡ���������
16 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct����ʼ����0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
17 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
18 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
19 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
20 #include <asm/io.h> // ����/���ͷ�ļ�������Ӳ���˿�����/���������䡣
21
// ������䶨��������Ƕ��ʽ������亯�����й�Ƕ��ʽ���Ļ�������������б����˵����
// ��Բ������ס�������䣨�������е���䣩������Ϊ����ʽʹ�ã���������__res�������ֵ��
// ��23�ж�����һ���Ĵ�������__res���ñ�������������һ���Ĵ����У��Ա��ڿ��ٷ��ʺͲ�����
// �����ָ���Ĵ���������eax������ô���ǿ��Ѹþ�д�ɡ�register char __res asm("ax");����
// ȡ��seg�е�ַaddr����һ���ֽڡ�
// ������seg - ��ѡ�����addr - ����ָ����ַ��
// �����%0 - eax (__res)�����룺%1 - eax (seg)��%2 - �ڴ��ַ (*(addr))��
22 #define get_seg_byte(seg,addr) ({ \
23 register char __res; \
24 __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \
25 :"=a" (__res):"0" (seg),"m" (*(addr))); \
26 __res;})
27
// ȡ��seg�е�ַaddr����һ�����֣�4�ֽڣ���
// ������seg - ��ѡ�����addr - ����ָ����ַ��
// �����%0 - eax (__res)�����룺%1 - eax (seg)��%2 - �ڴ��ַ (*(addr))��
28 #define get_seg_long(seg,addr) ({ \
29 register unsigned long __res; \
30 __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \
31 :"=a" (__res):"0" (seg),"m" (*(addr))); \
32 __res;})
33
// ȡfs�μĴ�����ֵ��ѡ�������
// �����%0 - eax (__res)��
34 #define _fs() ({ \
35 register unsigned short __res; \
36 __asm__("mov %%fs,%%ax":"=a" (__res):); \
37 __res;})
38
// ���¶�����һЩ����ԭ�͡�
39 void page_exception(void); // ҳ�쳣��ʵ����page_fault��mm/page.s��14����
40
41 void divide_error(void); // int0��kernel/asm.s��20����
42 void debug(void); // int1��kernel/asm.s��54����
43 void nmi(void); // int2��kernel/asm.s��58����
44 void int3(void); // int3��kernel/asm.s��62����
45 void overflow(void); // int4��kernel/asm.s��66����
46 void bounds(void); // int5��kernel/asm.s��70����
47 void invalid_op(void); // int6��kernel/asm.s��74����
48 void device_not_available(void); // int7��kernel/sys_call.s��158����
49 void double_fault(void); // int8��kernel/asm.s��98����
50 void coprocessor_segment_overrun(void); // int9��kernel/asm.s��78����
51 void invalid_TSS(void); // int10��kernel/asm.s��132����
52 void segment_not_present(void); // int11��kernel/asm.s��136����
53 void stack_segment(void); // int12��kernel/asm.s��140����
54 void general_protection(void); // int13��kernel/asm.s��144����
55 void page_fault(void); // int14��mm/page.s��14����
56 void coprocessor_error(void); // int16��kernel/sys_call.s��140����
57 void reserved(void); // int15��kernel/asm.s��82����
58 void parallel_interrupt(void); // int39��kernel/sys_call.s��295����
59 void irq13(void); // int45 Э�������жϴ�����kernel/asm.s��86����
60 void alignment_check(void); // int46��kernel/asm.s��148����
61
// ���ӳ���������ӡ�����жϵ����ơ������š����ó����EIP��EFLAGS��ESP��fs�μĴ���ֵ��
// �εĻ�ַ���εij��ȡ����̺�pid������š�10�ֽ�ָ���롣�����ջ���û����ݶΣ���
// ��ӡ16�ֽڵĶ�ջ���ݡ���Щ��Ϣ�����ڳ�����ԡ�
62 static void die(char * str,long esp_ptr,long nr)
63 {
64 long * esp = (long *) esp_ptr;
65 int i;
66
67 printk("%s: %04x\n\r",str,nr&0xffff);
// ���д�ӡ�����ʾ��ǰ���ý��̵�CS:EIP��EFLAGS��SS:ESP��ֵ����������!δ�ҵ�����Դ����֪������esp[0]
// ��Ϊͼ�е�esp0λ�á�������ǰ�����ֿ�����Ϊ��
// (1) EIP:\t%04x:%p\n -- esp[1]�Ƕ�ѡ�����cs����esp[0]��eip
// (2) EFLAGS:\t%p -- esp[2]��eflags
// (3) ESP:\t%04x:%p\n -- esp[4]��ԭss��esp[3]��ԭesp
68 printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n",
69 esp[1],esp[0],esp[2],esp[4],esp[3]);
70 printk("fs: %04x\n",_fs());
71 printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17));
72 if (esp[4] == 0x17) { // ��ԭssֵΪ0x17���û�ջ������ӡ��
73 printk("Stack: "); // �û�ջ�е�4������ֵ��16�ֽڣ���
74 for (i=0;i<4;i++)
75 printk("%p ",get_seg_long(0x17,i+(long *)esp[3]));
76 printk("\n");
77 }
78 str(i); // ȡ��ǰ�������������ţ�include/linux/sched.h��210�У���
79 printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); // ���̺ţ�����š�
80 for(i=0;i<10;i++)
81 printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0])));
82 printk("\n\r");
83 do_exit(11); /* play segment exception */
84 }
85
// ������Щ��do_��ͷ�ĺ�����asm.s�ж�Ӧ�жϴ���������õ�C������
86 void do_double_fault(long esp, long error_code)
87 {
88 die("double fault",esp,error_code);
89 }
90
91 void do_general_protection(long esp, long error_code)
92 {
93 die("general protection",esp,error_code);
94 }
95
96 void do_alignment_check(long esp, long error_code)
97 {
98 die("alignment check",esp,error_code);
99 }
100
101 void do_divide_error(long esp, long error_code)
102 {
103 die("divide error",esp,error_code);
104 }
105
// �����ǽ����жϺ�˳��ѹ���ջ�ļĴ���ֵ���μ�asm.s�����24--35�С�
106 void do_int3(long * esp, long error_code,
107 long fs,long es,long ds,
108 long ebp,long esi,long edi,
109 long edx,long ecx,long ebx,long eax)
110 {
111 int tr;
112
113 __asm__("str %%ax":"=a" (tr):"" (0)); // ȡ����Ĵ���ֵ��tr��
114 printk("eax\t\tebx\t\tecx\t\tedx\n\r%8x\t%8x\t%8x\t%8x\n\r",
115 eax,ebx,ecx,edx);
116 printk("esi\t\tedi\t\tebp\t\tesp\n\r%8x\t%8x\t%8x\t%8x\n\r",
117 esi,edi,ebp,(long) esp);
118 printk("\n\rds\tes\tfs\ttr\n\r%4x\t%4x\t%4x\t%4x\n\r",
119 ds,es,fs,tr);
120 printk("EIP: %8x CS: %4x EFLAGS: %8x\n\r",esp[0],esp[1],esp[2]);
121 }
122
123 void do_nmi(long esp, long error_code)
124 {
125 die("nmi",esp,error_code);
126 }
127
128 void do_debug(long esp, long error_code)
129 {
130 die("debug",esp,error_code);
131 }
132
133 void do_overflow(long esp, long error_code)
134 {
135 die("overflow",esp,error_code);
136 }
137
138 void do_bounds(long esp, long error_code)
139 {
140 die("bounds",esp,error_code);
141 }
142
143 void do_invalid_op(long esp, long error_code)
144 {
145 die("invalid operand",esp,error_code);
146 }
147
148 void do_device_not_available(long esp, long error_code)
149 {
150 die("device not available",esp,error_code);
151 }
152
153 void do_coprocessor_segment_overrun(long esp, long error_code)
154 {
155 die("coprocessor segment overrun",esp,error_code);
156 }
157
158 void do_invalid_TSS(long esp,long error_code)
159 {
160 die("invalid TSS",esp,error_code);
161 }
162
163 void do_segment_not_present(long esp,long error_code)
164 {
165 die("segment not present",esp,error_code);
166 }
167
168 void do_stack_segment(long esp,long error_code)
169 {
170 die("stack segment",esp,error_code);
171 }
172
173 void do_coprocessor_error(long esp, long error_code)
174 {
175 if (last_task_used_math != current)
176 return;
177 die("coprocessor error",esp,error_code);
178 }
179
180 void do_reserved(long esp, long error_code)
181 {
182 die("reserved (15,17-47) error",esp,error_code);
183 }
184
// �������쳣�����壩�жϳ����ʼ���ӳ����������ǵ��жϵ����ţ��ж���������
// set_trap_gate()��set_system_gate()��ʹ�����ж���������IDT�е������ţ�Trap Gate����
// ����֮�����Ҫ��������ǰ�����õ���Ȩ��Ϊ0��������3����˶ϵ������ж�int3������ж�
// overflow �ͱ߽�����ж� bounds �������κγ�����á� ��������������Ƕ��ʽ�������
// �μ�include/asm/system.h����36�С�39�С�
185 void trap_init(void)
186 {
187 int i;
188
189 set_trap_gate(0,÷_error); // ���ó������������ж�����ֵ��������ͬ��
190 set_trap_gate(1,&debug);
191 set_trap_gate(2,&nmi);
192 set_system_gate(3,&int3); /* int3-5 can be called from all */
193 set_system_gate(4,&overflow); /* int3-5 ���Ա����г���ִ�� */
194 set_system_gate(5,&bounds);
195 set_trap_gate(6,&invalid_op);
196 set_trap_gate(7,&device_not_available);
197 set_trap_gate(8,&double_fault);
198 set_trap_gate(9,&coprocessor_segment_overrun);
199 set_trap_gate(10,&invalid_TSS);
200 set_trap_gate(11,&segment_not_present);
201 set_trap_gate(12,&stack_segment);
202 set_trap_gate(13,&general_protection);
203 set_trap_gate(14,&page_fault);
204 set_trap_gate(15,&reserved);
205 set_trap_gate(16,&coprocessor_error);
206 set_trap_gate(17,&alignment_check);
// �����int17-47���������Ⱦ�����Ϊreserved���Ժ��Ӳ����ʼ��ʱ�����������Լ��������š�
207 for (i=18;i<48;i++)
208 set_trap_gate(i,&reserved);
// ����Э�������ж�0x2d��45����������������������������ж��������ò��п��ж���������
209 set_trap_gate(45,&irq13);
210 outb_p(inb_p(0x21)&0xfb,0x21); // ����8259A��оƬ��IRQ2�ж�����
211 outb(inb_p(0xA1)&0xdf,0xA1); // ����8259A��оƬ��IRQ13�ж�����
212 set_trap_gate(39,¶llel_interrupt); // ���ò��п�1���ж�0x27��������������
213 }
214
1 /*
2 * linux/kernel/system_call.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * system_call.s contains the system-call low-level handling routines.
9 * This also contains the timer-interrupt handler, as some of the code is
10 * the same. The hd- and flopppy-interrupts are also here.
11 *
12 * NOTE: This code handles signal-recognition, which happens every time
13 * after a timer-interrupt and after each system call. Ordinary interrupts
14 * don't handle signal-recognition, as that would clutter them up totally
15 * unnecessarily.
16 *
17 * Stack layout in 'ret_from_system_call':
18 *
19 * 0(%esp) - %eax
20 * 4(%esp) - %ebx
21 * 8(%esp) - %ecx
22 * C(%esp) - %edx
23 * 10(%esp) - original %eax (-1 if not system call)
24 * 14(%esp) - %fs
25 * 18(%esp) - %es
26 * 1C(%esp) - %ds
27 * 20(%esp) - %eip
28 * 24(%esp) - %cs
29 * 28(%esp) - %eflags
30 * 2C(%esp) - %oldesp
31 * 30(%esp) - %oldss
32 */
/*
* system_call.s�ļ�����ϵͳ���ã�system-call���ײ㴦���ӳ���������Щ����Ƚ����ƣ�
* ����ͬʱҲ����ʱ���жϴ�����timer-interrupt�������Ӳ�̺����̵��жϴ�������Ҳ�����
*
* ע�⣺��δ��봦���źţ�signal��ʶ����ÿ��ʱ���жϺ�ϵͳ����֮�����ʶ��һ��
* �жϹ��̲��������ź�ʶ����Ϊ���ϵͳ��ɻ��ҡ�
*
* ��ϵͳ���÷��أ�'ret_from_system_call'��ʱ��ջ�����ݼ�����19-30�С�
*/
# ����Linusԭע����һ���жϹ�����ָ����ϵͳ�����жϣ�int 0x80����ʱ���жϣ�int 0x20��
# ����������жϡ���Щ�жϻ����ں�̬���û�̬���������������Щ�жϹ�����Ҳ�����ź�ʶ��
# �Ļ������п�����ϵͳ�����жϺ�ʱ���жϹ����ж��źŵ�ʶ�����������ͻ����Υ�����ں�
# �������ռԭ�����ϵͳ���ޱ�Ҫ����Щ���������ж��д����źţ�Ҳ��������������
33
34 SIG_CHLD = 17 # ����SIG_CHLD�źţ��ӽ���ֹͣ���������
35
36 EAX = 0x00 # ��ջ�и����Ĵ�����ƫ��λ�á�
37 EBX = 0x04
38 ECX = 0x08
39 EDX = 0x0C
40 ORIG_EAX = 0x10 # �������ϵͳ���ã��������жϣ�ʱ����ֵΪ-1��
41 FS = 0x14
42 ES = 0x18
43 DS = 0x1C
44 EIP = 0x20 # 44 -- 48�� ��CPU�Զ���ջ��
45 CS = 0x24
46 EFLAGS = 0x28
47 OLDESP = 0x2C # ����Ȩ���仯ʱ��ԭ��ջָ��Ҳ����ջ��
48 OLDSS = 0x30
49
# ������Щ������ṹ��task_struct���б�����ƫ��ֵ���μ�include/linux/sched.h��105�п�ʼ��
50 state = 0 # these are offsets into the task-struct. # ����״̬�롣
51 counter = 4 # ��������ʱ�����(�ݼ�)���δ�����������ʱ��Ƭ��
52 priority = 8 # ����������������ʼ����ʱcounter=priority��Խ��������ʱ��Խ����
53 signal = 12 # ���ź�λͼ��ÿ������λ����һ���źţ��ź�ֵ=λƫ��ֵ+1��
54 sigaction = 16 # MUST be 16 (=len of sigaction) # sigaction�ṹ���ȱ�����16�ֽڡ�
55 blocked = (33*16) # �������ź�λͼ��ƫ������
56
# ���¶�����sigaction�ṹ�е�ƫ�������μ�include/signal.h����55�п�ʼ��
57 # offsets within sigaction
58 sa_handler = 0 # �źŴ������̵ľ��������������
59 sa_mask = 4 # �ź������롣
60 sa_flags = 8 # �źż���
61 sa_restorer = 12 # �ָ�����ָ�룬�μ�kernel/signal.c����˵����
62
63 nr_system_calls = 82 # Linux 0.12���ں��е�ϵͳ����������
64
65 ENOSYS = 38 # ϵͳ���úų����롣
66
67 /*
68 * Ok, I get parallel printer interrupts while using the floppy for some
69 * strange reason. Urgel. Now I just ignore them.
70 */
/* ���ˣ���ʹ������ʱ���յ��˲��д�ӡ���жϣ�����֡��ǣ����ڲ�������
*/
71 .globl _system_call,_sys_fork,_timer_interrupt,_sys_execve
72 .globl _hd_interrupt,_floppy_interrupt,_parallel_interrupt
73 .globl _device_not_available, _coprocessor_error
74
# ϵͳ���úŴ���ʱ�����س�����-ENOSYS��
75 .align 2 # �ڴ�4�ֽڶ��롣
76 bad_sys_call:
77 pushl $-ENOSYS # eax����-ENOSYS��
78 jmp ret_from_sys_call
# ����ִ�е��ȳ�����ڡ����ȳ���schedule()�ڣ�kernel/sched.c��119�д���ʼ��
# �����ȳ���schedule()����ʱ�ʹ�ret_from_sys_call����107�У�����ִ�С�
79 .align 2
80 reschedule:
81 pushl $ret_from_sys_call # ��ret_from_sys_call�ĵ�ַ��ջ��107�У���
82 jmp _schedule
#### int 0x80 --linuxϵͳ������ڵ㣨�����ж�int 0x80��eax���ǵ��úţ���
83 .align 2
84 _system_call:
85 push %ds # ����ԭ�μĴ���ֵ��
86 push %es
87 push %fs
88 pushl %eax # save the orig_eax # ����eaxԭֵ��
# һ��ϵͳ�������ɴ���3��������Ҳ���Բ���������������ջ��ebx��ecx��edx�з���ϵͳ
# ������ӦC���Ժ���������99�У��ĵ��ò������⼸���Ĵ�����ջ��˳������GNU gcc�涨�ģ�
# ebx�пɴ�ŵ�1��������ecx�д�ŵ�2��������edx�д�ŵ�3��������
# ϵͳ�������ɲμ�ͷ�ļ�include/unistd.h�е�150��200�е�ϵͳ���úꡣ
89 pushl %edx
90 pushl %ecx # push %ebx,%ecx,%edx as parameters
91 pushl %ebx # to the system call
# �ڱ�����μĴ���֮����ds,esָ���ں����ݶΣ���fsָ��ǰ�ֲ����ݶΣ���ָ��ִ�б�
# ��ϵͳ���õ��û���������ݶΡ�ע�⣬��Linux 0.12���ں˸��������Ĵ���������ڴ��
# ���ص��ģ����ǵĶλ�ַ�Ͷ�����ͬ���μ�fork.c������copy_mem()������
92 movl $0x10,%edx # set up ds,es to kernel space
93 mov %dx,%ds
94 mov %dx,%es
95 movl $0x17,%edx # fs points to local data space
96 mov %dx,%fs
97 cmpl _NR_syscalls,%eax # ���ú����������Χ�Ļ�����ת��
98 jae bad_sys_call
# �������������ĺ����ǣ����õ�ַ=[_sys_call_table + %eax * 4]���μ�������˵����
# sys_call_table[]��һ��ָ�����飬������include/linux/sys.h�У����������������ں�
# ����82��ϵͳ����C���������ĵ�ַ��
99 call _sys_call_table(,%eax,4) # ��ӵ���ָ������C������
100 pushl %eax # ��ϵͳ���÷���ֵ��ջ��
# ����101-106�в鿴��ǰ���������״̬��������ھ���״̬��state������0����ȥִ�е���
# ��������������ھ���״̬��������ʱ��Ƭ�Ѿ����꣨counter=0������Ҳȥִ�е��ȳ���
# ���統��̨�������еĽ���ִ�п����ն˶�д����ʱ����ôĬ�������¸ú�̨���������н���
# ���յ�SIGTTIN��SIGTTOU�źţ����½����������н��̴���ֹͣ״̬������ǰ�����������
# ���ء�
101 2:
102 movl _current,%eax # ȡ��ǰ�����̣����ݽṹָ����eax��
103 cmpl $0,state(%eax) # state
104 jne reschedule
105 cmpl $0,counter(%eax) # counter
106 je reschedule
# ������δ���ִ�д�ϵͳ����C�������غ��źŽ���ʶ�����������жϷ�������˳�ʱҲ
# ����ת��������д�������˳��жϹ��̣��������131���ϵĴ����������ж�int 16��
# �����б�ǰ�����Ƿ��dz�ʼ����task0��������ض�������ź�������Ĵ�����ֱ�ӷ��ء�
# 109���ϵ�_task��ӦC�����е�task[]���飬ֱ������task�൱������task[0]��
107 ret_from_sys_call:
108 movl _current,%eax
109 cmpl _task,%eax # task[0] cannot have signals
110 je 3f # ��ǰ(forward)��ת�����3���˳��жϴ�����
# ͨ����ԭ���ó������ѡ����ļ�����жϵ��ó����Ƿ����û��������������ֱ���˳��жϡ�
# ������Ϊ�������ں�ִ̬��ʱ������ռ���������������ź�����ʶ����������Ƚ�ѡ�����
# ��Ϊ�û�����ε�ѡ��� 0x000f��RPL=3���ֲ���������Σ����ж��Ƿ�Ϊ�û������������
# ��˵����ij���жϷ�����������ж�16����ת����107��ִ�е��ˣ�������ת�˳��жϳ���
# ���⣬���ԭ��ջ��ѡ�����Ϊ0x17����ԭ��ջ�����û����У���Ҳ˵������ϵͳ���õĵ�����
# �����û�������Ҳ�˳���
111 cmpw $0x0f,CS(%esp) # was old code segment supervisor ?
112 jne 3f
113 cmpw $0x17,OLDSS(%esp) # was stack segment = 0x17 ?
114 jne 3f
# ������δ��루115-128�����ڴ�����ǰ�����е��źš�����ȡ��ǰ����ṹ�е��ź�λͼ��32λ��
# ÿλ����1���źţ���Ȼ��������ṹ�е��ź����������Σ��룬�������������ź�λ��ȡ����ֵ
# ��С���ź�ֵ���ٰ�ԭ�ź�λͼ�и��źŶ�Ӧ��λ��λ����0��������ź�ֵ��Ϊ����֮һ��
# ��do_signal()��do_signal()�ڣ�kernel/signal.c,128���У����������13����ջ����Ϣ��
# ��do_signal()���źŴ�����������֮��������ֵ��Ϊ0���ٿ����Ƿ���Ҫ�л����̻��������
# �����źš�
115 movl signal(%eax),%ebx # ȡ�ź�λͼ��ebx��ÿ1λ����1���źţ���32���źš�
116 movl blocked(%eax),%ecx # ȡ���������Σ��ź�λͼ��ecx��
117 notl %ecx # ÿλȡ����
118 andl %ebx,%ecx # ������ɵ��ź�λͼ��
119 bsfl %ecx,%ecx # �ӵ�λ��λ0����ʼɨ��λͼ�����Ƿ���1��λ��
# ���У���ecx������λ��ƫ��ֵ�����ڼ�λ0--31����
120 je 3f # ���û���ź�����ǰ��ת�˳���
121 btrl %ecx,%ebx # ��λ���źţ�ebx����ԭsignalλͼ����
122 movl %ebx,signal(%eax) # ���±���signalλͼ��Ϣ��current->signal��
123 incl %ecx # ���źŵ���Ϊ��1��ʼ������1--32����
124 pushl %ecx # �ź�ֵ��ջ��Ϊ����do_signal�IJ���֮һ��
125 call _do_signal # ����C�����źŴ�������kernel/signal.c��128����
126 popl %ecx # ������ջ���ź�ֵ��
127 testl %eax, %eax # ���Է���ֵ������Ϊ0����ת��ǰ����2��101�У�����
128 jne 2b # see if we need to switch tasks, or do more signals
129 3: popl %eax # eax�к��е�100����ջ��ϵͳ���÷���ֵ��
130 popl %ebx
131 popl %ecx
132 popl %edx
133 addl $4, %esp # skip orig_eax # ������������ԭeaxֵ��
134 pop %fs
135 pop %es
136 pop %ds
137 iret
138
#### int16 -- �����������жϡ� ���ͣ����������롣
# ����һ���ⲿ�Ļ���Ӳ�����쳣����Э���������Լ���������ʱ���ͻ�ͨ��ERROR����
# ֪ͨCPU������������ڴ���Э�����������ij����źš�����תȥִ��C����math_error()
# ��kernel/math/error.c 11�������غ���ת�����ret_from_sys_call������ִ�С�
139 .align 2
140 _coprocessor_error:
141 push %ds
142 push %es
143 push %fs
144 pushl $-1 # fill in -1 for orig_eax # ��-1����������ϵͳ���á�
145 pushl %edx
146 pushl %ecx
147 pushl %ebx
148 pushl %eax
149 movl $0x10,%eax # ds,es��Ϊָ���ں����ݶΡ�
150 mov %ax,%ds
151 mov %ax,%es
152 movl $0x17,%eax # fs��Ϊָ��ֲ����ݶΣ�������������ݶΣ���
153 mov %ax,%fs
154 pushl $ret_from_sys_call # ��������÷��صĵ�ַ��ջ��
155 jmp _math_error # ִ��math_error()��kernel/math/error.c��11����
156
#### int7 -- �豸�����ڻ�Э�����������ڡ� ���ͣ����������롣
# ������ƼĴ��� CR0 ��EM��ģ�⣩��־��λ����CPU ִ��һ��Э������ָ��ʱ�ͻ�������
# �жϣ�����CPU�Ϳ����л���������жϴ�������ģ��Э������ָ�181�У���
# CR0�Ľ�����־TS���� CPUִ������ת��ʱ���õġ�TS ��������ȷ��ʲôʱ��Э�������е�
# ������CPU ����ִ�е�����ƥ���ˡ���CPU ������һ��Э������ת��ָ��ʱ����TS��λʱ��
# �ͻ��������жϡ���ʱ�Ϳ��Ա���ǰһ�������Э���������ݣ����ָ��������Э������ִ��
# ״̬��176�У����μ�kernel/sched.c��92�С����ж����ת�Ƶ����ret_from_sys_call
# ��ִ����ȥ����Ⲣ�����źţ���
157 .align 2
158 _device_not_available:
159 push %ds
160 push %es
161 push %fs
162 pushl $-1 # fill in -1 for orig_eax # ��-1����������ϵͳ���á�
163 pushl %edx
164 pushl %ecx
165 pushl %ebx
166 pushl %eax
167 movl $0x10,%eax # ds,es��Ϊָ���ں����ݶΡ�
168 mov %ax,%ds
169 mov %ax,%es
170 movl $0x17,%eax # fs��Ϊָ��ֲ����ݶΣ�������������ݶΣ���
171 mov %ax,%fs
# ��CR0�������ѽ�����־TS����ȡCR0ֵ��������Э�����������־EMû����λ��˵������
# EM������жϣ���ָ�����Э������״̬��ִ��C���� math_state_restore()�����ڷ���ʱ
# ȥִ��ret_from_sys_call���Ĵ��롣
172 pushl $ret_from_sys_call # ��������ת����õķ��ص�ַ��ջ��
173 clts # clear TS so that we can use math
174 movl %cr0,%eax
175 testl $0x4,%eax # EM (math emulation bit)
176 je _math_state_restore # ִ��math_state_restore()��kernel/sched.c��92�У���
# ��EM��־��λ����ȥִ����ѧ�������math_emulate()��
177 pushl %ebp
178 pushl %esi
179 pushl %edi
180 pushl $0 # temporary storage for ORIG_EIP
181 call _math_emulate # ����C������math/math_emulate.c��476����
182 addl $4,%esp # ������ʱ�洢��
183 popl %edi
184 popl %esi
185 popl %ebp
186 ret # �����ret����ת��ret_from_sys_call(107��)��
187
#### int32 -- (int 0x20) ʱ���жϴ��������ж�Ƶ������Ϊ100Hz(include/linux/sched.h,4)��
# ��ʱоƬ8253/8254����(kernel/sched.c,438)����ʼ���ġ��������jiffiesÿ10�����1��
# ��δ��뽫jiffies��1�����ͽ����ж�ָ���8259��������Ȼ���õ�ǰ��Ȩ����Ϊ��������
# C����do_timer(long CPL)�������÷���ʱתȥ��Ⲣ�����źš�
188 .align 2
189 _timer_interrupt:
190 push %ds # save ds,es and put kernel data space
191 push %es # into them. %fs is used by _system_call
192 push %fs # ����ds��es������ָ���ں����ݶΡ�fs������system_call��
193 pushl $-1 # fill in -1 for orig_eax # ��-1����������ϵͳ���á�
# �������DZ���Ĵ���eax��ecx��edx��������Ϊgcc�������ڵ��ú���ʱ���ᱣ�����ǡ�����Ҳ
# ������ebx�Ĵ�������Ϊ�ں���ret_from_sys_call�л��õ�����
194 pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
195 pushl %ecx # save those across function calls. %ebx
196 pushl %ebx # is saved as we use that in ret_sys_call
197 pushl %eax
198 movl $0x10,%eax # ds,es��Ϊָ���ں����ݶΡ�
199 mov %ax,%ds
200 mov %ax,%es
201 movl $0x17,%eax # fs��Ϊָ��ֲ����ݶΣ���������ݶΣ���
202 mov %ax,%fs
203 incl _jiffies
# ���ڳ�ʼ���жϿ���оƬʱû�в����Զ�EOI������������Ҫ��ָ�������Ӳ���жϡ�
204 movb $0x20,%al # EOI to interrupt controller #1
205 outb %al,$0x20
# ����Ӷ�ջ��ȡ��ִ��ϵͳ���ô����ѡ�����CS�μĴ���ֵ���еĵ�ǰ��Ȩ����(0��3)��ѹ��
# ��ջ����Ϊdo_timer�IJ�����do_timer()����ִ�������л�����ʱ�ȹ�������kernel/sched.c��
# 324��ʵ�֡�
206 movl CS(%esp),%eax
207 andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
208 pushl %eax
209 call _do_timer # 'do_timer(long CPL)' does everything from
210 addl $4,%esp # task switching to accounting ...
211 jmp ret_from_sys_call
212
#### ����sys_execve()ϵͳ���á�ȡ�жϵ��ó���Ĵ���ָ����Ϊ��������C����do_execve()��
# do_execve()��fs/exec.c��207��
213 .align 2
214 _sys_execve:
215 lea EIP(%esp),%eax # eaxָ���ջ�б����û�����eipָ�봦��
216 pushl %eax
217 call _do_execve
218 addl $4,%esp # ��������ʱѹ��ջ��EIPֵ��
219 ret
220
#### sys_fork()���ã����ڴ����ӽ��̣���system_call����2��ԭ����include/linux/sys.h�С�
# ���ȵ���C����find_empty_process()��ȡ��һ�����̺�last_pid�������ظ�����˵��Ŀǰ����
# ����������Ȼ�����copy_process()���ƽ��̡�
221 .align 2
222 _sys_fork:
223 call _find_empty_process # Ϊ�½���ȡ�ý��̺�last_pid����kernel/fork.c��143����
224 testl %eax,%eax # ��eax�з��ؽ��̺š������ظ������˳���
225 js 1f
226 push %gs
227 pushl %esi
228 pushl %edi
229 pushl %ebp
230 pushl %eax
231 call _copy_process # ����C����copy_process()��kernel/fork.c��68����
232 addl $20,%esp # ������������ѹջ���ݡ�
233 1: ret
234
#### int 46 -- (int 0x2E) Ӳ���жϴ���������ӦӲ���ж�����IRQ14��
# �������Ӳ�̲�����ɻ�����ͻᷢ�����ж��źš�(�μ�kernel/blk_drv/hd.c)��
# ������8259A�жϿ��ƴ�оƬ���ͽ���Ӳ���ж�ָ��(EOI)��Ȼ��ȡ����do_hd�еĺ���ָ�����edx
# �Ĵ����У�����do_hdΪNULL�������ж�edx����ָ���Ƿ�Ϊ�ա����Ϊ�գ����edx��ֵָ��
# unexpected_hd_interrupt()��������ʾ������Ϣ�������8259A��оƬ��EOIָ�������edx��
# ָ��ָ��ĺ���: read_intr()��write_intr()��unexpected_hd_interrupt()��
235 _hd_interrupt:
236 pushl %eax
237 pushl %ecx
238 pushl %edx
239 push %ds
240 push %es
241 push %fs
242 movl $0x10,%eax # ds,es��Ϊ�ں����ݶΡ�
243 mov %ax,%ds
244 mov %ax,%es
245 movl $0x17,%eax # fs��Ϊ���ó���ľֲ����ݶΡ�
246 mov %ax,%fs
# ���ڳ�ʼ���жϿ���оƬʱû�в����Զ�EOI������������Ҫ��ָ�������Ӳ���жϡ�
247 movb $0x20,%al
248 outb %al,$0xA0 # EOI to interrupt controller #1 # �ʹ�8259A��
249 jmp 1f # give port chance to breathe # ����jmp����ʱ���á�
250 1: jmp 1f
# do_hd����Ϊһ������ָ�룬������ֵread_intr()��write_intr()������ַ���ŵ�edx�Ĵ�����
# �ͽ�do_hdָ�������ΪNULL��Ȼ����Եõ��ĺ���ָ�룬����ָ��Ϊ�գ������ָ��ָ��C
# ����unexpected_hd_interrupt()���Դ���δ֪Ӳ���жϡ�
251 1: xorl %edx,%edx
252 movl %edx,_hd_timeout # hd_timeout��Ϊ0����ʾ���������ڹ涨ʱ���ڲ������жϡ�
253 xchgl _do_hd,%edx
254 testl %edx,%edx
255 jne 1f # ���գ�����ָ��ָ��C����unexpected_hd_interrupt()��
256 movl $_unexpected_hd_interrupt,%edx
257 1: outb %al,$0x20 # ��8259A��оƬEOIָ�����Ӳ���жϣ���
258 call *%edx # "interesting" way of handling intr.
259 pop %fs # �Ͼ����do_hdָ���C������
260 pop %es
261 pop %ds
262 popl %edx
263 popl %ecx
264 popl %eax
265 iret
266
#### int38 -- (int 0x26) �����������жϴ���������ӦӲ���ж�����IRQ6��
# �䴦�������������Ӳ�̵Ĵ�������һ������kernel/blk_drv/floppy.c����
# ������8259A�жϿ�������оƬ����EOIָ�Ȼ��ȡ����do_floppy�еĺ���ָ�����eax
# �Ĵ����У�����do_floppyΪNULL�������ж�eax����ָ���Ƿ�Ϊ�ա���Ϊ�գ����eax��ֵָ��
# unexpected_floppy_interrupt ()��������ʾ������Ϣ��������eaxָ��ĺ���: rw_interrupt,
# seek_interrupt,recal_interrupt,reset_interrupt��unexpected_floppy_interrupt��
267 _floppy_interrupt:
268 pushl %eax
269 pushl %ecx
270 pushl %edx
271 push %ds
272 push %es
273 push %fs
274 movl $0x10,%eax # ds,es��Ϊ�ں����ݶΡ�
275 mov %ax,%ds
276 mov %ax,%es
277 movl $0x17,%eax # fs��Ϊ���ó���ľֲ����ݶΡ�
278 mov %ax,%fs
279 movb $0x20,%al # ����8259A�жϿ�����EOIָ�����Ӳ���жϣ���
280 outb %al,$0x20 # EOI to interrupt controller #1
# do_floppyΪһ����ָ�룬������ֵʵ�ʴ���C����ָ�롣��ָ���ڱ������ŵ�eax�Ĵ�����ͽ�
# do_floppy�����ÿա�Ȼ�����eax��ԭָ���Ƿ�Ϊ�գ�������ʹָ��ָ��C����
# unexpected_floppy_interrupt()��
281 xorl %eax,%eax
282 xchgl _do_floppy,%eax
283 testl %eax,%eax # ���Ժ���ָ���Ƿ�=NULL?
284 jne 1f # ���գ���ʹָ��ָ��C����unexpected_floppy_interrupt()��
285 movl $_unexpected_floppy_interrupt,%eax
286 1: call *%eax # "interesting" way of handling intr. # ��ӵ��á�
287 pop %fs # �Ͼ����do_floppyָ��ĺ�����
288 pop %es
289 pop %ds
290 popl %edx
291 popl %ecx
292 popl %eax
293 iret
294
#### int 39 -- (int 0x27) ���п��жϴ�������ӦӲ���ж������ź�IRQ7��
# ���汾�ں˻�δʵ�֡�����ֻ�Ƿ���EOIָ�
295 _parallel_interrupt:
296 pushl %eax
297 movb $0x20,%al
298 outb %al,$0x20
299 popl %eax
300 iret
1 /*
2 * linux/kernel/mktime.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <time.h> // ʱ��ͷ�ļ��������˱�ʱ�����ݽṹtm��һЩ����ʱ�亯��ԭ�͡�
8
9 /*
10 * This isn't the library routine, it is only used in the kernel.
11 * as such, we don't care about years<1970 etc, but assume everything
12 * is ok. Similarly, TZ etc is happily ignored. We just do everything
13 * as easily as possible. Let's find something public for the library
14 * routines (although I think minix times is public).
15 */
16 /*
17 * PS. I hate whoever though up the year 1970 - couldn't they have gotten
18 * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy.
19 */
/*
* �ⲻ�ǿ⺯�����������ں�ʹ�á�������Dz�����С��1970�����ݵȣ����ٶ�һ�о���������
* ͬ����ʱ������TZ����Ҳ�Ⱥ��ԡ�����ֻ�Ǿ����ܼش������⡣������ҵ�һЩ�����Ŀ⺯��
* ����������Ϊminix��ʱ�亯���ǹ����ģ���
* ���⣬�Һ��Ǹ�����1970�꿪ʼ���� - �ѵ����ǾͲ���ѡ���һ�����꿪ʼ���Һ����������
* �����̻ʡ����̣���ʲô�����ں������Ǹ�Ƣ��������ˡ�
*/
20 #define MINUTE 60 // 1���ӵ�������
21 #define HOUR (60*MINUTE) // 1Сʱ��������
22 #define DAY (24*HOUR) // 1���������
23 #define YEAR (365*DAY) // 1���������
24
25 /* interestingly, we assume leap-years */
/* ��Ȥ�������ǿ��ǽ������� */
// ��������Ϊ���ޣ�������ÿ���¿�ʼʱ������ʱ�䡣
26 static int month[12] = {
27 0,
28 DAY*(31),
29 DAY*(31+29),
30 DAY*(31+29+31),
31 DAY*(31+29+31+30),
32 DAY*(31+29+31+30+31),
33 DAY*(31+29+31+30+31+30),
34 DAY*(31+29+31+30+31+30+31),
35 DAY*(31+29+31+30+31+30+31+31),
36 DAY*(31+29+31+30+31+30+31+31+30),
37 DAY*(31+29+31+30+31+30+31+31+30+31),
38 DAY*(31+29+31+30+31+30+31+31+30+31+30)
39 };
40
// �ú��������1970��1��1��0ʱ�������վ�������������Ϊ����ʱ�䡣
// ����tm�и��ֶ��Ѿ���init/main.c�б���ֵ����Ϣȡ��CMOS��
41 long kernel_mktime(struct tm * tm)
42 {
43 long res;
44 int year;
45
// ���ȼ���70�굽���ھ�������������Ϊ��2λ��ʾ��ʽ�����Ի���2000�����⡣���ǿ���
// ������ǰ������һ����������������⣺if (tm->tm_year<70) tm->tm_year += 100;
// ����UNIX�����y�Ǵ�1970�����𡣵�1972�����һ�����꣬��˹�3�꣨71��72��73��
// ���ǵ�1�����꣬������1970�꿪ʼ�����������㷽����Ӧ����Ϊ1 + (y - 3)/4����Ϊ
// (y + 1)/4��res = ��Щ�꾭��������ʱ�� + ÿ������ʱ��1�������ʱ�� + ���굽����ʱ
// �����������⣬month[]�������Ѿ���2�·ݵ������а�����������ʱ����������2�·�����
// ������ 1�졣��ˣ������겻�����겢�ҵ�ǰ�·ݴ��� 2�·ݵĻ������Ǿ�Ҫ��ȥ���졣��
// Ϊ��70�꿪ʼ�������Ե�����������жϷ����� (y + 2) �ܱ�4�����������ܳ���������
// �����Ͳ������ꡣ
46 year = tm->tm_year - 70;
47 /* magic offsets (y+1) needed to get leapyears right.*/
/* Ϊ�˻����ȷ����������������Ҫ����һ��ħ��ֵ(y+1) */
48 res = YEAR*year + DAY*((year+1)/4);
49 res += month[tm->tm_mon];
50 /* and (y+2) here. If it wasn't a leap-year, we have to adjust */
/* �Լ�(y+2)�����(y+2)�������꣬��ô���Ǿͱ�����е���(��ȥһ�������ʱ��)��*/
51 if (tm->tm_mon>1 && ((year+2)%4))
52 res -= DAY;
53 res += DAY*(tm->tm_mday-1); // �ټ��ϱ��¹�ȥ������������ʱ�䡣
54 res += HOUR*tm->tm_hour; // �ټ��ϵ����ȥ��Сʱ��������ʱ�䡣
55 res += MINUTE*tm->tm_min; // �ټ���1Сʱ�ڹ�ȥ�ķ�����������ʱ�䡣
56 res += tm->tm_sec; // �ټ���1�������ѹ���������
57 return res; // �����ڴ�1970����������������ʱ�䡣
58 }
59
1 /*
2 * linux/kernel/sched.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'sched.c' is the main kernel file. It contains scheduling primitives
9 * (sleep_on, wakeup, schedule etc) as well as a number of simple system
10 * call functions (type getpid(), which just extracts a field from
11 * current-task
12 */
/*
* 'sched.c'����Ҫ���ں��ļ������а����йص��ȵĻ�������(sleep_on��wakeup��schedule��)
* �Լ�һЩ��ϵͳ���ú���������getpid()�����ӵ�ǰ�����л�ȡһ���ֶΣ���
*/
// �����ǵ��ȳ���ͷ�ļ�������������ṹtask_struct����1����ʼ��������ݡ�����һЩ�Ժ�
// ����ʽ������й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������
13 #include <linux/sched.h>
14 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
15 #include <linux/sys.h> // ϵͳ����ͷ�ļ�������82��ϵͳ����C��������,��'sys_'��ͷ��
16 #include <linux/fdreg.h> // ����ͷ�ļ����������̿�����������һЩ���塣
17 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
18 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
19 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
20
21 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų�����sigaction�ṹ����������ԭ�͡�
22
// �ú�ȡ�ź�nr���ź�λͼ�ж�Ӧλ�Ķ�������ֵ���źű��1-32�������ź�5��λͼ��ֵ����
// 1<<(5-1) = 16 = 00010000b��
23 #define _S(nr) (1<<((nr)-1))
// ����SIGKILL��SIGSTOP�ź����������źŶ��ǿ�������(��1011,1111,1110,1111,1111b)��
24 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
25
// �ں˵��Ժ�������ʾ�����nr�Ľ��̺š�����״̬���ں˶�ջ�����ֽ�������Լ����
26 void show_task(int nr,struct task_struct * p)
27 {
28 int i,j = 4096-sizeof(struct task_struct);
29
30 printk("%d: pid=%d, state=%d, father=%d, child=%d, ",nr,p->pid,
31 p->state, p->p_pptr->pid, p->p_cptr ? p->p_cptr->pid : -1);
32 i=0;
33 while (i<j && !((char *)(p+1))[i]) // ���ָ���������ݽṹ�Ժ����0���ֽ�����
34 i++;
35 printk("%d/%d chars free in kstack\n\r",i,j);
36 printk(" PC=%08X.", *(1019 + (unsigned long *) p));
37 if (p->p_ysptr || p->p_osptr)
38 printk(" Younger sib=%d, older sib=%d\n\r",
39 p->p_ysptr ? p->p_ysptr->pid : -1,
40 p->p_osptr ? p->p_osptr->pid : -1);
41 else
42 printk("\n\r");
43 }
44
// ��ʾ�������������š����̺š�����״̬���ں˶�ջ�����ֽ�������Լ����
// NR_TASKS��ϵͳ�����ɵ�������(����)����(64��)��������include/kernel/sched.h ��6�С�
45 void show_state(void)
46 {
47 int i;
48
49 printk("\rTask-info:\n\r");
50 for (i=0;i<NR_TASKS;i++)
51 if (task[i])
52 show_task(i,task[i]);
53 }
54
// PC��8253��ʱоƬ������ʱ��Ƶ��ԼΪ1.193180MHz��Linux�ں�ϣ����ʱ�������жϵ�Ƶ����
// 100Hz��Ҳ��ÿ10ms����һ��ʱ���жϡ��������LATCH������8253оƬ�ij�ֵ���μ�438�С�
55 #define LATCH (1193180/HZ)
56
57 extern void mem_use(void); // [??]û���κεط���������øú�����
58
59 extern int timer_interrupt(void); // ʱ���жϴ�������kernel/system_call.s��176����
60 extern int system_call(void); // ϵͳ�����жϴ�������kernel/system_call.s��80����
61
// ÿ�������̣����ں�̬����ʱ�����Լ����ں�̬��ջ�����ﶨ����������ں�̬��ջ�ṹ��
// ���ﶨ���������ϣ�����ṹ��Ա��stack�ַ������Ա������Ϊһ����������ݽṹ�����ں�
// ̬��ջ����ͬһ�ڴ�ҳ�У����ԴӶ�ջ�μĴ���ss���Ի�������ݶ�ѡ�����
62 union task_union {
63 struct task_struct task;
64 char stack[PAGE_SIZE];
65 };
66
// ���ó�ʼ��������ݡ���ʼ������include/kernel/sched.h�У���156�п�ʼ��
67 static union task_union init_task = {INIT_TASK,};
68
// �ӿ�����ʼ����ĵδ���ʱ��ֵȫ�ֱ�����10ms/�δ𣩡�ϵͳʱ���ж�ÿ����һ�μ�һ���δ�
// ǰ������� volatile��Ӣ�Ľ������ı�ġ����ȶ�����˼��������ʵĺ������������
// ָ�����������ݿ��ܻ����ڱ����������Ķ��仯��ͨ���ڳ���������һ������ʱ�� ��������
// �������������ͨ�üĴ����У����� ebx������߷���Ч�ʡ���CPU����ֵ�ŵ� ebx�к�һ��
// �Ͳ����ٹ��ĸñ�����Ӧ�ڴ�λ���е����ݡ�����ʱ�������������ں˳����һ���жϹ��̣�
// �����ڴ��иñ�����ֵ��ebx�е�ֵ��������֮���¡�Ϊ�˽����������ʹ�����volatile
// �������ô��������øñ���ʱһ��Ҫ��ָ���ڴ�λ����ȡ����ֵ�����T��Ҫ�� gcc��Ҫ��
// jiffies �����Ż�������Ҳ��ҪŲ��λ�ã�������Ҫ���ڴ���ȡ��ֵ����Ϊʱ���жϴ�������
// �ȳ����������ֵ��
69 unsigned long volatile jiffies=0;
70 unsigned long startup_time=0; // ����ʱ�䡣��1970:0:0:0��ʼ��ʱ��������
// ������������ۼ���Ҫ������ʱ���������
71 int jiffies_offset = 0; /* # clock ticks to add to get "true
72 time". Should always be less than
73 1 second's worth. For time fanatics
74 who like to syncronize their machines
75 to WWV :-) */
/* Ϊ����ʱ�Ӷ���Ҫ���ӵ�ʱ����������Ի�á���ȷʱ�䡱����Щ�����������
* ���ܺͲ�Ӧ�ó���1�롣��������Ϊ����Щ��ʱ�侫ȷ��Ҫ����̵��ˣ�����ϲ
* ���Լ��Ļ���ʱ����WWVͬ�� :-)
*/
76
77 struct task_struct *current = &(init_task.task); // ��ǰ����ָ�루��ʼ��ָ������0����
78 struct task_struct *last_task_used_math = NULL; // ʹ�ù�Э�����������ָ�롣
79
// ��������ָ�����顣��1���ʼ��ָ���ʼ��������0�����������ݽṹ��
80 struct task_struct * task[NR_TASKS] = {&(init_task.task), };
81
// �����û���ջ����1K�����4K�ֽڡ����ں˳�ʼ�����������б������ں�ջ����ʼ�����
// �Ժ���������0���û�̬��ջ������������0֮ǰ�����ں�ջ���Ժ���������0��1����
// ��̬ջ������ṹ�������ö�ջss:esp�����ݶ�ѡ�����ָ�룩����head.s����23�С�
// ss������Ϊ�ں����ݶ�ѡ�����0x10����ָ��espָ�� user_stack�������һ����档����
// ��ΪIntel CPUִ�ж�ջ����ʱ���ȵݼ���ջָ��spֵ��Ȼ����spָ�봦������ջ���ݡ�
82 long user_stack [ PAGE_SIZE>>2 ] ;
83
84 struct {
85 long * a;
86 short b;
87 } stack_start = { & user_stack [PAGE_SIZE>>2] , 0x10 };
88 /*
89 * 'math_state_restore()' saves the current math information in the
90 * old math state array, and gets the new ones from the current task
91 */
/*
* ����ǰЭ���������ݱ��浽��Э������״̬�����У�������ǰ�����Э������
* ���ݼ��ؽ�Э��������
*/
// �������Ƚ������Ժú������Ա���ԭ�����Э������״̬�������ģ����ָ��µ��Ƚ�
// ���ĵ�ǰ�����Э������ִ��״̬��
92 void math_state_restore()
93 {
// �������û����(��һ��������ǵ�ǰ����)������"��һ������"��ָ�ձ�������ȥ������
94 if (last_task_used_math == current)
95 return;
// �ڷ���Э����������֮ǰҪ�ȷ�WAITָ�����ϸ�����ʹ����Э������������״̬��
96 __asm__("fwait");
97 if (last_task_used_math) {
98 __asm__("fnsave %0"::"m" (last_task_used_math->tss.i387));
99 }
// ���ڣ�last_task_used_mathָ��ǰ�����Ա���ǰ��������ȥʱʹ�á���ʱ�����ǰ
// �����ù�Э����������ָ���״̬������Ļ�˵���ǵ�һ��ʹ�ã����Ǿ���Э����������ʼ��
// ���������ʹ����Э��������־��
100 last_task_used_math=current;
101 if (current->used_math) {
102 __asm__("frstor %0"::"m" (current->tss.i387));
103 } else {
104 __asm__("fninit"::); // ��Э����������ʼ�����
105 current->used_math=1; // ����ʹ����Э��������־��
106 }
107 }
108
109 /*
110 * 'schedule()' is the scheduler function. This is GOOD CODE! There
111 * probably won't be any reason to change this, as it should work well
112 * in all circumstances (ie gives IO-bound processes good response etc).
113 * The one thing you might take a look at is the signal-handler code here.
114 *
115 * NOTE!! Task 0 is the 'idle' task, which gets called when no other
116 * tasks can run. It can not be killed, and it cannot sleep. The 'state'
117 * information in task[0] is never used.
118 */
/*
* 'schedule()'�ǵ��Ⱥ��������Ǹ��ܺõĴ��룡û���κ����ɶ��������ģ���Ϊ
* �����������еĻ����¹����������ܹ���IO-�߽紦���ܺõ���Ӧ�ȣ���ֻ��һ��
* ��ֵ�����⣬�Ǿ���������źŴ������롣
*
* ע�⣡������0�Ǹ�����('idle')����ֻ�е�û�����������������ʱ�ŵ���
* ���������ܱ�ɱ����Ҳ����˯�ߡ�����0�е�״̬��Ϣ'state'�Ǵ������õġ�
*/
119 void schedule(void)
120 {
121 int i,next,c;
122 struct task_struct ** p; // ����ṹָ���ָ�롣
123
124 /* check alarm, wake up any interruptible tasks that have got a signal */
/* ���alarm�����̵ı�����ʱֵ���������κ��ѵõ��źŵĿ��ж����� */
125
// ���������������һ������ʼѭ�����alarm����ѭ��ʱ������ָ���
126 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
127 if (*p) {
// ������ù�����ʱ��ʱtimeout�������Ѿ���ʱ����λ��ʱ��ʱֵ��������������ڿ�
// �ж�˯��״̬TASK_INTERRUPTIBLE�£�������Ϊ����״̬��TASK_RUNNING����
128 if ((*p)->timeout && (*p)->timeout < jiffies) {
129 (*p)->timeout = 0;
130 if ((*p)->state == TASK_INTERRUPTIBLE)
131 (*p)->state = TASK_RUNNING;
132 }
// ������ù�����Ķ�ʱֵalarm�������Ѿ�����(alarm<jiffies),�����ź�λͼ����SIGALRM
// �źţ�����������SIGALARM�źš�Ȼ����alarm�����źŵ�Ĭ�ϲ�������ֹ���̡�jiffies
// ��ϵͳ�ӿ�����ʼ����ĵδ�����10ms/�δ𣩡�������sched.h��139�С�
133 if ((*p)->alarm && (*p)->alarm < jiffies) {
134 (*p)->signal |= (1<<(SIGALRM-1));
135 (*p)->alarm = 0;
136 }
// ����ź�λͼ�г����������ź���������źţ����������ڿ��ж�״̬����������Ϊ����
// ״̬������'~(_BLOCKABLE & (*p)->blocked)'���ں��Ա��������źţ���SIGKILL��SIGSTOP
// ���ܱ�������
137 if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
138 (*p)->state==TASK_INTERRUPTIBLE)
139 (*p)->state=TASK_RUNNING; //��Ϊ��������ִ�У�״̬��
140 }
141
142 /* this is the scheduler proper: */
/* �����ǵ��ȳ������Ҫ���� */
143
144 while (1) {
145 c = -1;
146 next = 0;
147 i = NR_TASKS;
148 p = &task[NR_TASKS];
// ��δ���Ҳ�Ǵ�������������һ������ʼѭ���������������������������ۡ��Ƚ�ÿ��
// ����״̬�����counter����������ʱ��ĵݼ��δ������ֵ����һ��ֵ������ʱ�仹������
// next��ָ���ĸ�������š�
149 while (--i) {
150 if (!*--p)
151 continue;
152 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)
153 c = (*p)->counter, next = i;
154 }
// ����Ƚϵó���counterֵ������0�Ľ��������ϵͳ��û��һ�������е�������ڣ���ʱc
// ��ȻΪ-1��next=0�������˳�144�п�ʼ��ѭ����ִ��161���ϵ������л��������������
// ÿ�����������Ȩֵ������ÿһ�������counterֵ��Ȼ��ص�125�����±Ƚϡ�counter ֵ
// �ļ��㷽ʽΪ counter = counter /2 + priority��ע�⣬���������̲����ǽ��̵�״̬��
155 if (c) break;
156 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
157 if (*p)
158 (*p)->counter = ((*p)->counter >> 1) +
159 (*p)->priority;
160 }
// ������꣨������sched.h�У��ѵ�ǰ����ָ��currentָ�������Ϊnext�������л�
// �������������С���146����next����ʼ��Ϊ0�������ϵͳ��û���κ��������������ʱ��
// �� next ʼ��Ϊ0����˵��Ⱥ�������ϵͳ����ʱȥִ������0�� ��ʱ����0��ִ��pause()
// ϵͳ���ã����ֻ���ñ�������
161 switch_to(next); // �л��������Ϊnext����������֮��
162 }
163
//// pause()ϵͳ���á�ת����ǰ�����״̬Ϊ���жϵĵȴ�״̬�������µ��ȡ�
// ��ϵͳ���ý����½��̽���˯��״̬��ֱ���յ�һ���źš����ź�������ֹ���̻���ʹ����
// ����һ���źŲ�������ֻ�е�������һ���źţ������źŲ������������أ�pause()��
// �᷵�ء���ʱ pause()����ֵӦ���� -1������ errno����Ϊ EINTR�����ﻹû����ȫʵ��
// ��ֱ��0.95�棩��
164 int sys_pause(void)
165 {
166 current->state = TASK_INTERRUPTIBLE;
167 schedule();
168 return 0;
169 }
170
// �ѵ�ǰ������Ϊָ����˯��״̬�����жϵĻ��жϵģ�������˯�߶���ͷָ��ָ��ǰ����
// ��������p�ǵȴ��������ͷָ�롣ָ���Ǻ���һ��������ַ�ı������������pʹ����ָ���
// ָ����ʽ '**p'��������ΪC��������ֻ�ܴ�ֵ��û��ֱ�ӵķ�ʽ�ñ����ú����ı���øú���
// �����б�����ֵ������ָ��'*p'ָ���Ŀ�꣨����������ṹ����ı䣬���Ϊ�����ĵ��ø�
// ����������ԭ������ָ�������ֵ������Ҫ����ָ��'*p'��ָ�룬��'**p'���μ�����ǰʾ��ͼ��
// pָ���ʹ�������
// ����state������˯��ʹ�õ�״̬��TASK_UNINTERRUPTIBLE��TASK_INTERRUPTIBLE�����ڲ���
// �ж�˯��״̬��TASK_UNINTERRUPTIBLE����������Ҫ�ں˳�������wake_up()������ȷ����֮��
// ���ڿ��ж�˯��״̬��TASK_INTERRUPTIBLE������ͨ���źš�����ʱ���ֶλ��� ����Ϊ����
// ״̬TASK_RUNNING����
// *** ע�⣬���ڱ��ں˴��벻�Ǻܳ��죬���������˯����صĴ������һЩ���⣬�������
171 static inline void __sleep_on(struct task_struct **p, int state)
172 {
173 struct task_struct *tmp;
174
// ��ָ����Ч�����˳�����ָ����ָ�Ķ��������NULL����ָ�뱾������Ϊ0)��
// �����ǰ����������0��������(impossible!)��
175 if (!p)
176 return;
177 if (current == &(init_task.task))
178 panic("task[0] trying to sleep");
// ��tmpָ���Ѿ��ڵȴ������ϵ�����(����еĻ�)������inode->i_wait�����ҽ�˯�߶���ͷ
// �ĵȴ�ָ��ָ��ǰ���������Ͱѵ�ǰ������뵽�� *p�ĵȴ������С�Ȼ��ǰ������
// Ϊָ���ĵȴ�״̬����ִ�����µ��ȡ�
179 tmp = *p;
180 *p = current;
181 current->state = state;
182 repeat: schedule();
// ֻ�е�����ȴ�������ʱ��������ֻ᷵�ص������ʾ�����ѱ���ȷ�ػ��Ѳ�ִ�С�
// ����ȴ������л��еȴ������Ҷ���ͷָ�� *p ��ָ��������ǵ�ǰ����ʱ��˵��
// �ڱ��������ȴ����к����������ȴ����С���������Ӧ��ҲҪ�������������
// ���Լ�Ӧ��˳������Щ���������е������ѣ�������ォ�ȴ�����ͷ��ָ��������Ϊ
// ����״̬�����Լ�����Ϊ�����жϵȴ�״̬�����Լ�Ҫ�ȴ���Щ���������е�������
// ��ִ��ʱ�����ѱ�����Ȼ������ִ�е��ȳ���
183 if (*p && *p != current) {
184 (**p).state = 0;
185 current->state = TASK_UNINTERRUPTIBLE;
186 goto repeat;
187 }
// ִ�е����˵������������������ִ�С���ʱ�ȴ�����ͷָ��Ӧ��ָ����������Ϊ
// �գ���������������⣬������ʾ������Ϣ�����������ͷָ��ָ��������ǰ��������
// ������*p = tmp���� ��ȷʵ��������һ�����������л�������tmp��Ϊ�գ�����
// ����֮�����Ƚ�����е������ڻ��Ѻ�����ʱ���ջ�ѵȴ�����ͷָ���ó�NULL��
188 if (!*p)
189 printk("Warning: *P = NULL\n\r");
190 if (*p = tmp)
191 tmp->state=0;
192 }
193
// ����ǰ������Ϊ���жϵĵȴ�״̬��TASK_INTERRUPTIBLE����������ͷָ��*pָ���ĵȴ�
// ������
194 void interruptible_sleep_on(struct task_struct **p)
195 {
196 __sleep_on(p,TASK_INTERRUPTIBLE);
197 }
198
// �ѵ�ǰ������Ϊ�����жϵĵȴ�״̬��TASK_UNINTERRUPTIBLE��������˯�߶���ͷָ��ָ��
// ��ǰ����ֻ����ȷ�ػ���ʱ�Ż᷵�ء��ú����ṩ�˽������жϴ�������֮���ͬ�����ơ�
199 void sleep_on(struct task_struct **p)
200 {
201 __sleep_on(p,TASK_UNINTERRUPTIBLE);
202 }
203
// ���� *pָ�������*p������ȴ�����ͷָ�롣�����µȴ������Dz����ڵȴ�����ͷָ��
// ���ģ���˻��ѵ���������ȴ����е��������������Ѿ�����ֹͣ����״̬������ʾ
// ������Ϣ��
204 void wake_up(struct task_struct **p)
205 {
206 if (p && *p) {
207 if ((**p).state == TASK_STOPPED) // ����ֹͣ״̬��
208 printk("wake_up: TASK_STOPPED");
209 if ((**p).state == TASK_ZOMBIE) // ���ڽ���״̬��
210 printk("wake_up: TASK_ZOMBIE");
211 (**p).state=0; // ��Ϊ����״̬TASK_RUNNING��
212 }
213 }
214
215 /*
216 * OK, here are some floppy things that shouldn't be in the kernel
217 * proper. They are here because the floppy needs a timer, and this
218 * was the easiest way of doing it.
219 */
/*
* ���ˣ������↑ʼ��һЩ�й����̵��ӳ�����Ӧ�÷����ں˵���Ҫ����
* �еġ������Ƿ�����������Ϊ������Ҫ��ʱ���������������������ġ�
*/
// ����220 -- 281�д������ڴ���������ʱ�����Ķ���δ���֮ǰ���ȿ�һ�¿��豸һ����
// �й�������������floppy.c�������˵���� ���ߵ��Ķ����̿��豸��������ʱ��������
// �δ��롣����ʱ�䵥λ��1���δ� = 1/100�롣
// ��������wait_motor[]���ڴ�ŵȴ�������������������ת�ٵĽ���ָ�롣��������0-3
// �ֱ��Ӧ����A--D������ mon_timer[]��Ÿ�����������������Ҫ�ĵδ�����������Ĭ��
// ����ʱ��Ϊ50���δ�0.5�룩������ moff_timer[] ��Ÿ�����������ͣת֮ǰ��ά��
// ��ʱ�䡣�������趨Ϊ10000���δ�100�룩��
220 static struct task_struct * wait_motor[4] = {NULL,NULL,NULL,NULL};
221 static int mon_timer[4]={0,0,0,0};
222 static int moff_timer[4]={0,0,0,0};
// ���������Ӧ�����������е�ǰ��������Ĵ������üĴ���ÿλ�Ķ������£�
// λ7-4���ֱ����������D-A�����������1 - ������0 - �رա�
// λ3 ��1 - ����DMA���ж�����0 - ��ֹDMA���ж�����
// λ2 ��1 - �������̿������� 0 - ��λ���̿�������
// λ1-0��00 - 11������ѡ����Ƶ�����A-D��
// �������ó�ֵΪ������DMA���ж���������FDC��
223 unsigned char current_DOR = 0x0C;
224
// ָ������������������ת״̬����ȴ�ʱ�䡣
// ����nr -- ������(0--3)������ֵΪ�δ�����
// �ֲ�����selected��ѡ��������־��blk_drv/floppy.c��123�У���mask����ѡ������Ӧ��
// ��������Ĵ����������������λ��mask��4λ�Ǹ��������������־��
225 int ticks_to_floppy_on(unsigned int nr)
226 {
227 extern unsigned char selected;
228 unsigned char mask = 0x10 << nr;
229
// ϵͳ�����4������������Ԥ�����ú�ָ������nrͣת֮ǰ��Ҫ������ʱ�䣨100�룩��Ȼ��
// ȡ��ǰDOR�Ĵ���ֵ����ʱ����mask�У�����ָ������������������־��λ��
230 if (nr>3)
231 panic("floppy_on: nr>3");
232 moff_timer[nr]=10000; /* 100 s = very big :-) */ // ͣתά��ʱ�䡣
233 cli(); /* use floppy_off to turn it off */ // ���жϡ�
234 mask |= current_DOR;
// �����ǰû��ѡ�������������ȸ�λ����������ѡ��λ��Ȼ����ָ������ѡ��λ��
235 if (!selected) {
236 mask &= 0xFC;
237 mask |= nr;
238 }
// �����������Ĵ����ĵ�ǰֵ��Ҫ���ֵ��ͬ������FDC��������˿������ֵ(mask)������
// ���Ҫ�����������ﻹû��������������Ӧ����������������ʱ��ֵ��HZ/2 = 0.5��� 50��
// �δ𣩡����Ѿ���������������������ʱΪ2���δ����������� do_floppy_timer()���ȵ�
// �����жϵ�Ҫ��ִ�б��ζ�ʱ�����Ҫ�ɡ��˺���µ�ǰ��������Ĵ���current_DOR��
239 if (mask != current_DOR) {
240 outb(mask,FD_DOR);
241 if ((mask ^ current_DOR) & 0xf0)
242 mon_timer[nr] = HZ/2;
243 else if (mon_timer[nr] < 2)
244 mon_timer[nr] = 2;
245 current_DOR = mask;
246 }
247 sti(); // ���жϡ�
248 return mon_timer[nr]; // ����������������ʱ��ֵ��
249 }
250
// �ȴ�ָ�������������������һ��ʱ�䣬Ȼ�ء�
// ����ָ����������������������ת���������ʱ��Ȼ��˯�ߵȴ����ڶ�ʱ�жϹ����л�һֱ
// �ݼ��ж������趨����ʱֵ������ʱ���ڣ��ͻỽ������ĵȴ����̡�
251 void floppy_on(unsigned int nr)
252 {
// ���жϡ��������������ʱ��û������һֱ�ѵ�ǰ������Ϊ�����ж�˯��״̬������ȴ�����
// ���еĶ����С�Ȼ���жϡ�
253 cli();
254 while (ticks_to_floppy_on(nr))
255 sleep_on(nr+wait_motor);
256 sti();
257 }
258
// �ùر���Ӧ��������ͣת��ʱ����3�룩��
// ����ʹ�øú�����ȷ�ر�ָ������������������↑��100��֮��Ҳ�ᱻ�رա�
259 void floppy_off(unsigned int nr)
260 {
261 moff_timer[nr]=3*HZ;
262 }
263
// ���̶�ʱ�����ӳ���������������ʱֵ������ر�ͣת��ʱֵ�����ӳ������ʱ�Ӷ�ʱ
// �жϹ����б����ã����ϵͳÿ����һ���δ�(10ms)�ͻᱻ����һ�Σ���ʱ�������↑����
// ͣת��ʱ����ֵ�����ijһ������ͣת��ʱ��������������Ĵ�����������λ��λ��
264 void do_floppy_timer(void)
265 {
266 int i;
267 unsigned char mask = 0x10;
268
269 for (i=0 ; i<4 ; i++,mask <<= 1) {
270 if (!(mask & current_DOR)) // �������DORָ����������������
271 continue;
272 if (mon_timer[i]) { // �������������ʱ�����ѽ��̡�
273 if (!--mon_timer[i])
274 wake_up(i+wait_motor);
275 } else if (!moff_timer[i]) { // �������ͣת��ʱ����
276 current_DOR &= ~mask; // ��λ��Ӧ��������λ������
277 outb(current_DOR,FD_DOR); // ������������Ĵ�����
278 } else
279 moff_timer[i]--; // ��������ͣת��ʱ�ݼ���
280 }
281 }
282
// �����ǹ��ڶ�ʱ���Ĵ��롣������64����ʱ����
283 #define TIME_REQUESTS 64
284
// ��ʱ�������ṹ�Ͷ�ʱ�����顣�ö�ʱ������ר���ڹ������ر�������������ﶨʱ������
// �������Ͷ�ʱ�������ִ�Linuxϵͳ�еĶ�̬��ʱ����Dynamic Timer���������ں�ʹ�á�
285 static struct timer_list {
286 long jiffies; // ��ʱ�δ�����
287 void (*fn)(); // ��ʱ��������
288 struct timer_list * next; // ����ָ����һ����ʱ����
289 } timer_list[TIME_REQUESTS], * next_timer = NULL; // next_timer�Ƕ�ʱ������ͷָ�롣
290
// ���Ӷ�ʱ�����������Ϊָ���Ķ�ʱֵ(�δ���)����Ӧ�Ĵ�������ָ�롣
// ������������floppy.c�����øú���ִ��������ر��������ʱ������
// ����jiffies �C ��10����Ƶĵδ�����*fn()- ��ʱʱ�䵽ʱִ�еĺ�����
291 void add_timer(long jiffies, void (*fn)(void))
292 {
293 struct timer_list * p;
294
// �����ʱ��������ָ��Ϊ�գ����˳���������жϡ�
295 if (!fn)
296 return;
297 cli();
// �����ʱֵ<=0�������̵����䴦�������Ҹö�ʱ�������������С�
298 if (jiffies <= 0)
299 (fn)();
300 else {
// ����Ӷ�ʱ�������У���һ�������
301 for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
302 if (!p->fn)
303 break;
// ����Ѿ������˶�ʱ�����飬��ϵͳ����J��������ʱ�����ݽṹ������Ӧ��Ϣ��������
// ����ͷ��
304 if (p >= timer_list + TIME_REQUESTS)
305 panic("No more time requests free");
306 p->fn = fn;
307 p->jiffies = jiffies;
308 p->next = next_timer;
309 next_timer = p;
// �������ʱֵ��С��������������ʱ��ȥ����ǰ����Ҫ�ĵδ����������ڴ�����ʱ��ʱ
// ֻҪ�鿴����ͷ�ĵ�һ��Ķ�ʱ�Ƿ��ڼ��ɡ�[[?? ��γ������û�п�����ȫ�������
// ����Ķ�ʱ��ֵС��ԭ��ͷһ����ʱ��ֵʱ������������ѭ���У�����ʱ����Ӧ�ý�����
// ������һ����ʱ��ֵ��ȥ�µĵ�1���Ķ�ʱֵ���������1����ʱֵ<=��2�������2��
// ��ʱֵ�۳���1����ֵ���ɣ������������ѭ���н��д�����]]
310 while (p->next && p->next->jiffies < p->jiffies) {
311 p->jiffies -= p->next->jiffies;
312 fn = p->fn;
313 p->fn = p->next->fn;
314 p->next->fn = fn;
315 jiffies = p->jiffies;
316 p->jiffies = p->next->jiffies;
317 p->next->jiffies = jiffies;
318 p = p->next;
319 }
320 }
321 sti();
322 }
323
//// ʱ���ж�C��������������sys_call.s�е�_timer_interrupt��189�У������á�
// ����cpl�ǵ�ǰ��Ȩ��0��3����ʱ���жϷ���ʱ����ִ�еĴ���ѡ����е���Ȩ����
// cpl=0ʱ��ʾ�жϷ���ʱ����ִ���ں˴��룻cpl=3ʱ��ʾ�жϷ���ʱ����ִ���û����롣
// ����һ����������ִ��ʱ��Ƭ����ʱ������������л�����ִ��һ����ʱ���¹�����
324 void do_timer(long cpl)
325 {
326 static int blanked = 0;
327
// �����ж��Ƿ���һ��ʱ�������Ļ������blankout�������blankcount������Ϊ�㣬
// ���ߺ�����ʱ���ʱ��blankintervalΪ0�Ļ�����ô���Ѿ����ں���״̬��������־
// blanked = 1����������Ļ�ָ���ʾ����blankcount������Ϊ�㣬��ݼ�֮�����Ҹ�λ
// ������־��
328 if (blankcount || !blankinterval) {
329 if (blanked)
330 unblank_screen();
331 if (blankcount)
332 blankcount--;
333 blanked = 0;
// ����Ļ���������־δ��λ��������Ļ�������������ú�����־��
334 } else if (!blanked) {
335 blank_screen();
336 blanked = 1;
337 }
// ���Ŵ���Ӳ�̲�����ʱ���⡣���Ӳ�̳�ʱ�����ݼ�֮��Ϊ0�������Ӳ�̷��ʳ�ʱ������
338 if (hd_timeout)
339 if (!--hd_timeout)
340 hd_times_out(); // Ӳ�̷��ʳ�ʱ������blk_drv/hdc��318�У���
341
// ���������������������رշ�����(��0x61�ڷ��������λλ0��1��λ0����8253
// ������2�Ĺ�����λ1����������)��
342 if (beepcount) // ����������ʱ��δ�����chr_drv/console.c,950�У���
343 if (!--beepcount)
344 sysbeepstop();
345
// �����ǰ��Ȩ��(cpl)Ϊ0����ߣ���ʾ���ں˳����ڹ����������ں˴�������ʱ��stime
// ������[ Linus���ں˳���ͳ��Ϊ�����û�(supervisor)�ij���sys_call.s��207��
// �ϵ�Ӣ��ע�͡����ֳƺ�������Intel CPU �ֲᡣ] ���cpl > 0�����ʾ��һ���û�����
// �ڹ���������utime��
346 if (cpl)
347 current->utime++;
348 else
349 current->stime++;
350
// ����ж�ʱ�����ڣ���������1����ʱ����ֵ��1������ѵ���0���������Ӧ�Ĵ�������
// �����ô�������ָ����Ϊ�ա�Ȼ��ȥ�����ʱ����next_timer�Ƕ�ʱ��������ͷָ�롣
351 if (next_timer) {
352 next_timer->jiffies--;
353 while (next_timer && next_timer->jiffies <= 0) {
354 void (*fn)(void); // ���������һ������ָ�붨�壡��L
355
356 fn = next_timer->fn;
357 next_timer->fn = NULL;
358 next_timer = next_timer->next;
359 (fn)(); // ���ö�ʱ����������
360 }
361 }
// �����ǰ���̿�����FDC����������Ĵ�������������λ����λ�ģ���ִ�����̶�ʱ����
362 if (current_DOR & 0xf0)
363 do_floppy_timer();
// �����������ʱ�仹û�꣬���˳��������õ�ǰ�������м���ֵΪ0������������ʱ���ж�ʱ
// �����ں˴����������أ��������ִ�е��Ⱥ�����
364 if ((--current->counter)>0) return;
365 current->counter=0;
366 if (!cpl) return; // �����ں�̬��������counterֵ���е��ȡ�
367 schedule();
368 }
369
// ϵͳ���ù��� - ���ñ�����ʱʱ��ֵ(��)��
// ������seconds����0���������¶�ʱֵ��������ԭ��ʱʱ�̻�ʣ��ļ��ʱ�䡣����0��
// �������ݽṹ�б�����ʱֵalarm�ĵ�λ��ϵͳ�δ�1�δ�Ϊ10���룩������ϵͳ������
// ���ö�ʱ����ʱϵͳ�δ�ֵjiffies��ת���ɵδ�λ�Ķ�ʱֵ֮�ͣ���'jiffies + HZ*��ʱ
// ��ֵ'��������������������Ϊ��λ�Ķ�ʱֵ����˱���������Ҫ�����ǽ������ֵ�λ��ת����
// ���г���HZ = 100�����ں�ϵͳ����Ƶ�ʡ�������include/sched.h��4���ϡ�
// ����seconds���µĶ�ʱʱ��ֵ����λ���롣
370 int sys_alarm(long seconds)
371 {
372 int old = current->alarm;
373
374 if (old)
375 old = (old - jiffies) / HZ;
376 current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
377 return (old);
378 }
379
// ȡ��ǰ���̺�pid��
380 int sys_getpid(void)
381 {
382 return current->pid;
383 }
384
// ȡ�����̺�ppid��
385 int sys_getppid(void)
386 {
387 return current->p_pptr->pid;
388 }
389
// ȡ�û���uid��
390 int sys_getuid(void)
391 {
392 return current->uid;
393 }
394
// ȡ��Ч���û���euid��
395 int sys_geteuid(void)
396 {
397 return current->euid;
398 }
399
// ȡ���gid��
400 int sys_getgid(void)
401 {
402 return current->gid;
403 }
404
// ȡ��Ч�����egid��
405 int sys_getegid(void)
406 {
407 return current->egid;
408 }
409
// ϵͳ���ù��� -- ���Ͷ�CPU��ʹ������Ȩ�����˻�����J����
// Ӧ������incrementΪ����0��ֵ�������ʹ����Ȩ����
410 int sys_nice(long increment)
411 {
412 if (current->priority-increment>0)
413 current->priority -= increment;
414 return 0;
415 }
416
// �ں˵��ȳ���ij�ʼ���ӳ���
417 void sched_init(void)
418 {
419 int i;
420 struct desc_struct * p; // ���������ṹָ�롣
421
// Linuxϵͳ����֮�����ں˲����졣�ں˴���ᱻ�����ġ�Linus���Լ�������������Щ
// �ؼ��Ե����ݽṹ�������POSIX���IJ����ݡ����������������ж���䲢�ޱ�Ҫ������
// ��Ϊ�������Լ��Լ��������ں˴�����ˡ�
422 if (sizeof(struct sigaction) != 16) // sigaction�Ǵ���й��ź�״̬�Ľṹ��
423 panic("Struct sigaction MUST be 16 bytes");
// ��ȫ���������������ó�ʼ��������0��������״̬���������;ֲ����ݱ���������
// FIRST_TSS_ENTRY��FIRST_LDT_ENTRY��ֵ�ֱ���4��5��������include/linux/sched.h
// �У�gdt ��һ�������������飨include/linux/head.h ����ʵ���϶�Ӧ���� head.s ��
// ��234���ϵ�ȫ������������ַ��_gdt������� gdt + FIRST_TSS_ENTRY ��Ϊ
// gdt[FIRST_TSS_ENTRY]������gdt[4]����Ҳ�� gdt �����4��ĵ�ַ�� �μ�
// include/asm/system.h,��65�п�ʼ��
424 set_tss_desc(gdt+FIRST_TSS_ENTRY,&(init_task.task.tss));
425 set_ldt_desc(gdt+FIRST_LDT_ENTRY,&(init_task.task.ldt));
// ��������������������ע��i=1��ʼ�����Գ�ʼ��������������ڣ�����������ṹ
// �������ļ�include/linux/head.h�С�
426 p = gdt+2+FIRST_TSS_ENTRY;
427 for(i=1;i<NR_TASKS;i++) {
428 task[i] = NULL;
429 p->a=p->b=0;
430 p++;
431 p->a=p->b=0;
432 p++;
433 }
434 /* Clear NT, so that we won't have troubles with that later on */
/* �����־�Ĵ����е�λNT�������Ժ�Ͳ������鷳 */
// EFLAGS�е�NT��־λ���ڿ��������Ƕ���á���NTλ��λʱ����ô��ǰ�ж�����ִ��
// IRETָ��ʱ�ͻ����������л���NTָ��TSS�е�back_link�ֶ��Ƿ���Ч��NT=0ʱ��Ч��
435 __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); // ��λNT��־��
// ������0 �� TSS��ѡ������ص�����Ĵ���tr�����ֲ�����������ѡ������ص��ֲ�����
// �����Ĵ���ldtr�С�ע�⣡���ǽ�GDT����ӦLDT��������ѡ������ص�ldtr��ֻ��ȷ��
// ��һ�Σ��Ժ�������LDT�ļ��أ���CPU����TSS�е�LDT���Զ����ء�
436 ltr(0); // ������include/linux/sched.h ��157-158��
437 lldt(0); // ���в�����0��������š�
// ����������ڳ�ʼ�� 8253��ʱ����ͨ��0��ѡ������ʽ3�������Ƽ�����ʽ��ͨ��0��
// ������Ž����жϿ�����оƬ��IRQ0�ϣ���ÿ10���뷢��һ��IRQ0����LATCH�dz�ʼ
// ��ʱ����ֵ��
438 outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
439 outb_p(LATCH & 0xff , 0x40); /* LSB */ // ��ʱֵ���ֽڡ�
440 outb(LATCH >> 8 , 0x40); /* MSB */ // ��ʱֵ���ֽڡ�
// ����ʱ���жϴ���������������ʱ���ж��ţ������жϿ����������룬����ʱ���жϡ�
// Ȼ������ϵͳ�����ж��š������������ж���������IDT���������ĺ궨�����ļ�
// include/asm/system.h�е�33��39�д������ߵ�����μ�system.h�ļ���ʼ����˵����
441 set_intr_gate(0x20,&timer_interrupt);
442 outb(inb_p(0x21)&~0x01,0x21);
443 set_system_gate(0x80,&system_call);
444 }
445
1 /*
2 * linux/kernel/signal.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct����ʼ����0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
8 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
9 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
10
11 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źŲ�������ԭ�͡�
12 #include <errno.h> // ������ͷ�ļ�����������ŷ��ų�����
13
// ��ȡ��ǰ�����ź�����λͼ��������������룩��sgetmask�ɷֽ�Ϊsignal-get-mask���������ơ�
14 int sys_sgetmask()
15 {
16 return current->blocked;
17 }
18
// �����µ��ź�����λͼ���ź�SIGKILL��SIGSTOP���ܱ����Ρ�����ֵ��ԭ�ź�����λͼ��
19 int sys_ssetmask(int newmask)
20 {
21 int old=current->blocked;
22
23 current->blocked = newmask & ~(1<<(SIGKILL-1)) & ~(1<<(SIGSTOP-1));
24 return old;
25 }
26
// ��Ⲣȡ�ý����յ��ĵ������Σ����������źš���δ�����źŵ�λͼ��������set�С�
27 int sys_sigpending(sigset_t *set)
28 {
29 /* fill in "set" with signals pending but blocked. */
/* �û�δ�������ұ������źŵ�λͼ����setָ����ָλ�ô� */
// ������֤�����ṩ���û��洢�ռ�Ӧ��4���ֽڡ�Ȼ��ѻ�δ�������ұ������źŵ�λͼ����
// setָ����ָλ�ô���
30 verify_area(set,4);
31 put_fs_long(current->blocked & current->signal, (unsigned long *)set);
32 return 0;
33 }
34
35 /* atomically swap in the new signal mask, and wait for a signal.
36 *
37 * we need to play some games with syscall restarting. We get help
38 * from the syscall library interface. Note that we need to coordinate
39 * the calling convention with the libc routine.
40 *
41 * "set" is just the sigmask as described in 1003.1-1988, 3.3.7.
42 * It is assumed that sigset_t can be passed as a 32 bit quantity.
43 *
44 * "restart" holds a restart indication. If it's non-zero, then we
45 * install the old mask, and return normally. If it's zero, we store
46 * the current mask in old_mask and block until a signal comes in.
47 */
/* �Զ��ظ������µ��ź������룬���ȴ��źŵĵ�����
*
* ������Ҫ��ϵͳ���ã�syscall����һЩ���������ǻ��ϵͳ���ÿ�ӿ�ȡ��ijЩ��Ϣ��
* ע�⣬������Ҫ�ѵ��ù�����libc���е��ӳ���ͳһ���ǡ�
*
* "set" ����POSIX��1003.1-1988��3.3.7�������������������sigmask��
* ������Ϊ����sigset_t�ܹ���Ϊһ��32λ�����ݡ�
*
* "restart"�б���������ָʾ��־�����Ϊ��0ֵ����ô���Ǿ�����ԭ���������룬
* �����������ء������Ϊ0����ô���ǾͰѵ�ǰ�������뱣����oldmask��
* �����������̣�ֱ���յ��κ�һ���ź�Ϊֹ��
*/
// ��ϵͳ������ʱ�ѽ����ź��������滻�ɲ����и�����set��Ȼ�������̣�ֱ���յ�һ��
// �ź�Ϊֹ��
// restart��һ�����жϵ�ϵͳ��������������־������1�ε��ø�ϵͳ����ʱ������0������
// �ڸú����л�ѽ���ԭ���������� blocked����������old_mask���������� restartΪ��0
// ֵ����˵����̵�2�ε��ø�ϵͳ����ʱ�����ͻ�ָ�����ԭ��������old_mask�е������롣
48 int sys_sigsuspend(int restart, unsigned long old_mask, unsigned long set)
49 {
// pause()ϵͳ���ý����µ������Ľ��̽���˯��״̬��ֱ���յ�һ���źš����źŻ�����ֹ
// ���̵�ִ�У����ߵ��½���ȥִ����Ӧ���źŲ�������
50 extern int sys_pause(void);
51
// ���restart��־��Ϊ0����ʾ�������ó����������������ǻָ�ǰ�汣����old_mask�е�
// ԭ���������롣��������-EINTR��ϵͳ���ñ��ź��жϣ���
52 if (restart) {
53 /* we're restarting */ /* ����������������ϵͳ���� */
54 current->blocked = old_mask;
55 return -EINTR;
56 }
// �����ʾrestart��־��ֵ��0����ʾ��1�ε��á�������������restart��־����Ϊ1����
// ������̵�ǰ������ blocked �� old_mask�У����ѽ��̵��������滻�� set��Ȼ�����
// pause()�ý���˯�ߣ��ȴ��źŵĵ������������յ�һ���ź�ʱ��pause() �ͻ᷵�أ�����
// ���̻�ȥִ���źŴ���������Ȼ���÷��� -ERESTARTNOINTR ���˳������������˵��
// �ڴ������źź�Ҫ�ص���ϵͳ�����м������У�����ϵͳ���ò��ᱻ�жϡ�
57 /* we're not restarting. do the work */
/* ���Dz��������������У���ô�ɻ�� */
58 *(&restart) = 1;
59 *(&old_mask) = current->blocked;
60 current->blocked = set;
61 (void) sys_pause(); /* return after a signal arrives */
62 return -ERESTARTNOINTR; /* handle the signal, and come back */
63 }
64
// ����sigaction���ݵ�fs���ݶ�to���������ں˿ռ临�Ƶ��û����������ݶ��С�
65 static inline void save_old(char * from,char * to)
66 {
67 int i;
68
// ������֤to�����ڴ�ռ��Ƿ��㹻��Ȼ���һ��sigaction�ṹ��Ϣ���Ƶ�fs�Σ��û���
// �ռ��С��꺯��put_fs_byte()��include/asm/segment.h��ʵ�֡�
69 verify_area(to, sizeof(struct sigaction));
70 for (i=0 ; i< sizeof(struct sigaction) ; i++) {
71 put_fs_byte(*from,to);
72 from++;
73 to++;
74 }
75 }
76
// ��sigaction���ݴ�fs���ݶ�fromλ�ø��Ƶ�to���������û����ݿռ�ȡ���ں����ݶ��С�
77 static inline void get_new(char * from,char * to)
78 {
79 int i;
80
81 for (i=0 ; i< sizeof(struct sigaction) ; i++)
82 *(to++) = get_fs_byte(from++);
83 }
84
// signal()ϵͳ���á�������sigaction()��Ϊָ�����źŰ�װ�µ��źž��(�źŴ�������)��
// �źž���������û�ָ���ĺ�����Ҳ������SIG_DFL��Ĭ�Ͼ������SIG_IGN�����ԣ���
// ����signum --ָ�����źţ�handler -- ָ���ľ����restorer �C�ָ�����ָ�룬�ú�����
// Libc ���ṩ���������źŴ������������ָ�ϵͳ���÷���ʱ�����Ĵ�����ԭ��ֵ�Լ�ϵͳ
// ���õķ���ֵ���ͺ���ϵͳ����û��ִ�й��źŴ��������ֱ�ӷ��ص��û�����һ���� ����
// ����ԭ�źž����
85 int sys_signal(int signum, long handler, long restorer)
86 {
87 struct sigaction tmp;
88
// ������֤�ź�ֵ����Ч��Χ��1--32���ڣ����Ҳ������ź�SIGKILL����SIGSTOP������Ϊ��
// �����źŲ��ܱ����̲���
89 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
90 return -EINVAL;
// Ȼ������ṩ�IJ����齨sigaction�ṹ���ݡ�sa_handler��ָ�����źŴ����������������
// sa_mask��ִ���źŴ������ʱ���ź������롣sa_flags��ִ��ʱ��һЩ��־��ϡ������趨
// ���źŴ������ֻʹ��1�κ�ͻָ���Ĭ��ֵ���������ź����Լ��Ĵ���������յ���
91 tmp.sa_handler = (void (*)(int)) handler;
92 tmp.sa_mask = 0;
93 tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
94 tmp.sa_restorer = (void (*)(void)) restorer; // ����ָ���������ָ�롣
// ����ȡ���ź�ԭ���Ĵ�������������ø��źŵ�sigaction�ṹ�����ԭ�źž����
95 handler = (long) current->sigaction[signum-1].sa_handler;
96 current->sigaction[signum-1] = tmp;
97 return handler;
98 }
99
// sigaction()ϵͳ���á��ı�������յ�һ���ź�ʱ�IJ�����signum�dz���SIGKILL�����
// �κ��źš�[����²�����action����Ϊ�� ]���²�������װ����� oldactionָ�벻Ϊ�գ�
// ��ԭ������������oldaction���ɹ���0������Ϊ-EINVAL��
100 int sys_sigaction(int signum, const struct sigaction * action,
101 struct sigaction * oldaction)
102 {
103 struct sigaction tmp;
104
// ������֤�ź�ֵ����Ч��Χ��1--32���ڣ����Ҳ������ź�SIGKILL����SIGSTOP������Ϊ��
// �����źŲ��ܱ����̲���
105 if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP)
106 return -EINVAL;
// ���źŵ�sigaction�ṹ�������µIJ����������������oldactionָ�벻Ϊ�յĻ�����
// ԭ����ָ�뱣�浽oldaction��ָ��λ�á�
107 tmp = current->sigaction[signum-1];
108 get_new((char *) action,
109 (char *) (signum-1+current->sigaction));
110 if (oldaction)
111 save_old((char *) &tmp,(char *) oldaction);
// ��������ź����Լ����źž�����յ�������������Ϊ0�������������α��źš�
112 if (current->sigaction[signum-1].sa_flags & SA_NOMASK)
113 current->sigaction[signum-1].sa_mask = 0;
114 else
115 current->sigaction[signum-1].sa_mask |= (1<<(signum-1));
116 return 0;
117 }
118
119 /*
120 * Routine writes a core dump image in the current directory.
121 * Currently not implemented.
122 */
/*
* �ڵ�ǰĿ¼�в���core dumpӳ���ļ����ӳ���Ŀǰ��û��ʵ�֡�
*/
123 int core_dump(long signr)
124 {
125 return(0); /* We didn't do a dump */
126 }
127
// ϵͳ���õ��жϴ����������������ź�Ԥ����������kernel/sys_call.s,119�У������
// �������Ҫ�����ǽ��źŴ���������뵽�û������ջ�У����ڱ�ϵͳ���ý������غ�����
// ִ���źž������Ȼ�����ִ���û��ij���
// �����IJ����ǽ���ϵͳ���ô�������sys_call.s��ʼ��ֱ�����ñ�������sys_call.s
// ��125�У�ǰ��ѹ���ջ��ֵ����Щֵ��������sys_call.s�еĴ����У���
// �� CPUִ���ж�ָ��ѹ����û�ջ��ַss��esp����־�Ĵ���eflags�ͷ��ص�ַcs��eip��
// �� ��85--91���ڸս���system_callʱѹ��ջ�ĶμĴ���ds��es��fs�Լ��Ĵ���eax
// ��orig_eax����edx��ecx��ebx��ֵ��
// �� ��100�е���sys_call_table��ѹ��ջ�е���Ӧϵͳ���ô��������ķ���ֵ��eax����
// �� ��124��ѹ��ջ�еĵ�ǰ�������ź�ֵ��signr����
128 int do_signal(long signr,long eax,long ebx, long ecx, long edx, long orig_eax,
129 long fs, long es, long ds,
130 long eip, long cs, long eflags,
131 unsigned long * esp, long ss)
132 {
133 unsigned long sa_handler;
134 long old_eip=eip;
135 struct sigaction * sa = current->sigaction + signr - 1;
136 int longs; // �� current->sigaction[signr-1]��
137
138 unsigned long * tmp_esp;
139
// �����ǵ�����䡣��������notdefʱ���ӡ�����Ϣ��
140 #ifdef notdef
141 printk("pid: %d, signr: %x, eax=%d, oeax = %d, int=%d\n",
142 current->pid, signr, eax, orig_eax,
143 sa->sa_flags & SA_INTERRUPT);
144 #endif
// �������ϵͳ���ö��������ж�ִ�й����е��õ�������ʱ�� roig_eax ֵΪ -1�� �μ�
// sys_call.s ��144�� ����䡣��˵� orig_eax������ -1 ʱ��˵������ij��ϵͳ���õ�
// �������˱��������� kernel/exit.c �� waitpid() �����У�����յ���SIGCHLD �źţ�
// �����ڶ��ܵ�����fs/pipe.c�йܵ���ǰ�����ݵ�û�ж����κ����ݵ�����£������յ�
// ���κ�һ�����������źţ����� -ERESTARTSYS ����ֵ���ء�����ʾ���̿��Ա��жϣ�
// �����ڼ���ִ�к����������ϵͳ���á�������-ERESTARTNOINTR˵���ڴ������źź�Ҫ��
// ���ص�ԭϵͳ�����м������У���ϵͳ���ò��ᱻ�жϡ��μ�ǰ���62�С�
// ����������˵���������ϵͳ�����е��õı�������������Ӧϵͳ���õķ����� eax����
// -ERESTARTSYS�� -ERESTARTNOINTRʱ��������Ĵ�����ʵ���ϻ�û�������ص��û������У���
145 if ((orig_eax != -1) &&
146 ((eax == -ERESTARTSYS) || (eax == -ERESTARTNOINTR))) {
// ���ϵͳ���÷������� -ERESTARTSYS����������ϵͳ���ã������� sigaction �к��б�־
// SA_INTERRUPT��ϵͳ���ñ��ź��жϺ���������ϵͳ���ã������ź�ֵС�� SIGCONT����
// �ź�ֵ����SIGTTOU�����źŲ���SIGCONT��SIGSTOP��SIGTSTP��SIGTTIN ��SIGTTOU������
// ��ϵͳ���õķ���ֵΪeax = -EINTR�������ź��жϵ�ϵͳ���á�
147 if ((eax == -ERESTARTSYS) && ((sa->sa_flags & SA_INTERRUPT) ||
148 signr < SIGCONT || signr > SIGTTOU))
149 *(&eax) = -EINTR;
150 else {
// ����ͻָ����̼Ĵ���eax�ڵ���ϵͳ����֮ǰ��ֵ�����Ұ�ԭ����ָ��ָ��ص�2�ֽڡ���
// �������û�����ʱ���ó�����������ִ�б��ź��жϵ�ϵͳ���á�
151 *(&eax) = orig_eax;
152 *(&eip) = old_eip -= 2;
153 }
154 }
// ����źž��ΪSIG_IGN��1��Ĭ�Ϻ��Ծ�������źŽ��д�����ֱ�ӷ��ء�
155 sa_handler = (unsigned long) sa->sa_handler;
156 if (sa_handler==1)
157 return(1); /* Ignore, see if there are more signals... */
// ������ΪSIG_DFL��0��Ĭ�ϴ�����������ݾ�����źŽ��зֱ�����
158 if (!sa_handler) {
159 switch (signr) {
// ����ź�������������Ҳ����֮�������ء�
160 case SIGCONT:
161 case SIGCHLD:
162 return(1); /* Ignore, ... */
163
// ����ź�������4���ź�֮һ����ѵ�ǰ����״̬��Ϊֹͣ״̬TASK_STOPPED������ǰ����
// �����̶�SIGCHLD�źŵ� sigaction������־ SA_NOCLDSTOP �������ӽ���ִֹͣ�л��ּ�
// ��ִ��ʱ��Ҫ����SIGCHLD�źţ�û����λ����ô�������̷���SIGCHLD�źš�
164 case SIGSTOP:
165 case SIGTSTP:
166 case SIGTTIN:
167 case SIGTTOU:
168 current->state = TASK_STOPPED;
169 current->exit_code = signr;
170 if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
171 SA_NOCLDSTOP))
172 current->p_pptr->signal |= (1<<(SIGCHLD-1));
173 return(1); /* Reschedule another event */
174
// ����ź�������6���ź�֮һ����ô���źŲ�����core dump�������˳���Ϊsignr|0x80
// ����do_exit()�˳��������˳�������ź�ֵ��do_exit()�IJ����Ƿ�����ͳ����ṩ���˳�
// ״̬��Ϣ������Ϊwait()��waitpid()������״̬��Ϣ���μ�sys/wait.h�ļ���13-18�С�
// wait()��waitpid()������Щ��Ϳ���ȡ���ӽ��̵��˳�״̬����ӽ�����ֹ��ԭ���źţ���
175 case SIGQUIT:
176 case SIGILL:
177 case SIGTRAP:
178 case SIGIOT:
179 case SIGFPE:
180 case SIGSEGV:
181 if (core_dump(signr))
182 do_exit(signr|0x80);
183 /* fall through */
184 default:
185 do_exit(signr);
186 }
187 }
188 /*
189 * OK, we're invoking a handler
190 */
/*
* OK���������������źž�����õ�����
*/
// ������źž��ֻ�豻����һ�Σ��þ���ÿա�ע�⣬���źž����ǰ���Ѿ�������
// sa_handlerָ���С�
// ��ϵͳ���ý����ں�ʱ���û����ص�ַ��eip��cs�����������ں�̬ջ�С�������δ�
// �����ں�̬��ջ���û�����ϵͳ����ʱ�Ĵ���ָ�� eip Ϊָ���źŴ��������ͬʱҲ��
// sa_restorer��signr������������(���SA_NOMASKû��λ)��eax��ecx��edx��Ϊ�����Լ�
// ԭ����ϵͳ���õij���ָ�뼰��־�Ĵ���ֵѹ���û���ջ�� ����ڱ���ϵͳ�����ж�
// �����û�����ʱ������ִ���û����źž������Ȼ���ټ���ִ���û�����
191 if (sa->sa_flags & SA_ONESHOT)
192 sa->sa_handler = NULL;
// ���ں�̬ջ���û�����ϵͳ������һ������ָ��ָ��eipָ����źŴ������������C����
// �Ǵ�ֵ��������˸�eip��ֵʱ��Ҫʹ�� "*(&eip)" ����ʽ�����⣬��������ź��Լ���
// ��������յ��ź��Լ�����Ҳ��Ҫ�����̵�������ѹ���ջ��
// ������ע�⣬ʹ�����·�ʽ����193�У�����ͨC���������������Dz������õġ���Ϊ��
// ��������ʱ��ջ�ϵIJ������ᱻ�����߶���������֮���Կ���ʹ�����ַ�ʽ������Ϊ�ú���
// �Ǵӻ������б����õģ������ں������غ������û�аѵ���do_signal()ʱ������
// ������������eip����Ȼ�ڶ�ջ�С�
// sigaction�ṹ��sa_mask�ֶθ������ڵ�ǰ�źž�����ź�������������ִ���ڼ�Ӧ�ñ�
// ���ε��źż���ͬʱ�������źž��ִ�е��ź�Ҳ�ᱻ���Ρ� ������sa_flags��ʹ����
// SA_NOMASK��־����ô�����źž��ִ�е��źŽ����ᱻ���ε�����������ź��Լ��Ĵ�
// ����������յ��ź��Լ�����Ҳ��Ҫ�����̵��ź�������ѹ���ջ��
193 *(&eip) = sa_handler;
194 longs = (sa->sa_flags & SA_NOMASK)?7:8;
// ��ԭ���ó�����û���ջָ��������չ7����8�������֣�������ŵ����źž���IJ����ȣ���
// ������ڴ�ʹ���������������ڴ泬���������ҳ�ȣ���
195 *(&esp) -= longs;
196 verify_area(esp,longs*4);
// ���û���ջ�д��µ��ϴ��sa_restorer���ź�signr��������blocked�����SA_NOMASK
// ��λ����eax��ecx��edx��eflags���û�����ԭ����ָ�롣
197 tmp_esp=esp;
198 put_fs_long((long) sa->sa_restorer,tmp_esp++);
199 put_fs_long(signr,tmp_esp++);
200 if (!(sa->sa_flags & SA_NOMASK))
201 put_fs_long(current->blocked,tmp_esp++);
202 put_fs_long(eax,tmp_esp++);
203 put_fs_long(ecx,tmp_esp++);
204 put_fs_long(edx,tmp_esp++);
205 put_fs_long(eflags,tmp_esp++);
206 put_fs_long(old_eip,tmp_esp++);
207 current->blocked |= sa->sa_mask; // ����������(������)����sa_mask�е���λ��
208 return(0); /* Continue, execute handler */
209 }
210
1 /*
2 * linux/kernel/exit.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define DEBUG_PROC_TREE // ������š����Խ���������
8
9 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�(Linus��minix��������)
10 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ�Լ��źŲ�������ԭ�͡�
11 #include <sys/wait.h> // �ȴ�����ͷ�ļ�������ϵͳ����wait()��waitpid()����س������š�
12
13 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
14 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
15 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
16 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
17
18 int sys_pause(void); // �ѽ�����Ϊ˯��״̬��ֱ���յ��źţ�kernel/sched.c��164�У���
19 int sys_close(int fd); // �ر�ָ���ļ���ϵͳ���ã�fs/open.c��219�У���
20
//// �ͷ�ָ������ռ�õ�����ۼ����������ݽṹռ�õ��ڴ�ҳ�档
// ����p ���������ݽṹָ�롣�ú����ں���� sys_kill() �� sys_waitpid() �����б����á�
// ɨ������ָ������� task[] ��Ѱ��ָ������������ҵ�����������ո�����ۣ�Ȼ���ͷ�
// ���������ݽṹ��ռ�õ��ڴ�ҳ�棬���ִ�е��Ⱥ������ڷ���ʱ�����˳����������������
// ����û���ҵ�ָ�������Ӧ������ں�panicJ��
21 void release(struct task_struct * p)
22 {
23 int i;
24
// �������������ṹָ��ΪNULL���˳��������ָ��ָ��ǰ��������ʾ������Ϣ�˳���
25 if (!p)
26 return;
27 if (p == current) {
28 printk("task releasing itself\n\r");
29 return;
30 }
// ɨ������ṹָ�����飬Ѱ��ָ��������p������ҵ������ÿ�����ָ�������ж�Ӧ�����
// ��������ṹ֮��Ĺ���ָ�룬�ͷ�����p���ݽṹռ�õ��ڴ�ҳ�档�����ִ�е��ȳ���
// ���غ��˳������û���ҵ�ָ��������p����˵���ں˴�������ˣ�����ʾ������Ϣ��������
// �������Ӳ��ֵĴ�����ָ������p��˫��������ɾ����
31 for (i=1 ; i<NR_TASKS ; i++)
32 if (task[i]==p) {
33 task[i]=NULL;
34 /* Update links */ /* �������� */
// ���p����������ϣ����ӽ��̣����ñ����ϵı��ڽ���ָ������µı��ڽ��̡����p
// �������µ��ӽ��̣����ñ����µı����ӽ���ָ����ڵ��Ͻ��̡� �������p �������µ�
// �ӽ��̣�����Ҫ�����丸���̵������ӽ���ָ��cptrΪָ��p�ı����ӽ��̡�
// ָ��osptr��old sibling pointer��ָ���p�ȴ������ֵܽ��̡�
// ָ��ysptr��younger sibling pointer��ָ���p�����ֵܽ��̡�
// ָ��pptr��parent pointer��ָ��p�ĸ����̡�
// ָ��cptr��child pointer���Ǹ�����ָ�����£���������ӽ��̡�
35 if (p->p_osptr)
36 p->p_osptr->p_ysptr = p->p_ysptr;
37 if (p->p_ysptr)
38 p->p_ysptr->p_osptr = p->p_osptr;
39 else
40 p->p_pptr->p_cptr = p->p_osptr;
41 free_page((long)p);
42 schedule();
43 return;
44 }
45 panic("trying to release non-existent task");
46 }
47
48 #ifdef DEBUG_PROC_TREE
// ��������˷���DEBUG_PROC_TREE�������ʱ�������´��롣
49 /*
50 * Check to see if a task_struct pointer is present in the task[] array
51 * Return 0 if found, and 1 if not found.
52 */
/*
* ���task[]�������Ƿ����һ��ָ����task_struct�ṹָ��p��
* ���������0������1��
*/
// �������ṹָ��p��
53 int bad_task_ptr(struct task_struct *p)
54 {
55 int i;
56
57 if (!p)
58 return 0;
59 for (i=0 ; i<NR_TASKS ; i++)
60 if (task[i] == p)
61 return 0;
62 return 1;
63 }
64
65 /*
66 * This routine scans the pid tree and make sure the rep invarient still
67 * holds. Used for debugging only, since it's very slow....
68 *
69 * It looks a lot scarier than it really is.... we're doing nothing more
70 * than verifying the doubly-linked list found in p_ysptr and p_osptr,
71 * and checking it corresponds with the process tree defined by p_cptr and
72 * p_pptr;
73 */
/*
* ����ĺ�������ɨ�����������ȷ�����Ĺ���������Ȼ��ȷ�������ڵ�ʽ��
* ��Ϊ�ú����Ƚ���....
*
* �ú�������ȥҪ��ʵ�ʵĿֲ�.... ��ʵ���ǽ�����֤��ָ��p_ysptr��
* p_osptr���ɵ�˫���������������������ָ��p_cptr��p_pptr���ɵ�
* ������֮��Ĺ�ϵ��
*/
// ����������
74 void audit_ptree()
75 {
76 int i;
77
// ɨ��ϵͳ�еij�����0��������������������4��ָ�루pptr��cptr��ysptr��osptr��
// ����ȷ�ԡ�����������ۣ��Ϊ����������
78 for (i=1 ; i<NR_TASKS ; i++) {
79 if (!task[i])
80 continue;
// �������ĸ�����ָ��p_pptrû��ָ���κν��̣��������������в����ڣ�������ʾ������Ϣ
// �����棬pid��N�ĸ��������������⡱����������cptr��ysptr��osptr�������Ʋ�����
81 if (bad_task_ptr(task[i]->p_pptr))
82 printk("Warning, pid %d's parent link is bad\n",
83 task[i]->pid);
84 if (bad_task_ptr(task[i]->p_cptr))
85 printk("Warning, pid %d's child link is bad\n",
86 task[i]->pid);
87 if (bad_task_ptr(task[i]->p_ysptr))
88 printk("Warning, pid %d's ys link is bad\n",
89 task[i]->pid);
90 if (bad_task_ptr(task[i]->p_osptr))
91 printk("Warning, pid %d's os link is bad\n",
92 task[i]->pid);
// �������ĸ�����ָ��p_pptrָ�����Լ�������ʾ������Ϣ�����棬pid��N�ĸ���������
// ָ��ָ�����Լ�������������cptr��ysptr��osptr�������Ʋ�����
93 if (task[i]->p_pptr == task[i])
94 printk("Warning, pid %d parent link points to self\n");
95 if (task[i]->p_cptr == task[i])
96 printk("Warning, pid %d child link points to self\n");
97 if (task[i]->p_ysptr == task[i])
98 printk("Warning, pid %d ys link points to self\n");
99 if (task[i]->p_osptr == task[i])
100 printk("Warning, pid %d os link points to self\n");
// ��������б��Լ��ȴ����ı����ֵܽ��̣���ô�ͼ�������Ƿ��й�ͬ�ĸ����̣���������
// ���ֽ��̵�ysptrָ���Ƿ���ȷ��ָ���̡�������ʾ������Ϣ��
101 if (task[i]->p_osptr) {
102 if (task[i]->p_pptr != task[i]->p_osptr->p_pptr)
103 printk(
104 "Warning, pid %d older sibling %d parent is %d\n",
105 task[i]->pid, task[i]->p_osptr->pid,
106 task[i]->p_osptr->p_pptr->pid);
107 if (task[i]->p_osptr->p_ysptr != task[i])
108 printk(
109 "Warning, pid %d older sibling %d has mismatched ys link\n",
110 task[i]->pid, task[i]->p_osptr->pid);
111 }
// ��������б��Լ����ı����ֵܽ��̣���ô�ͼ�������Ƿ��й�ͬ�ĸ����̣���������
// С�ܽ��̵�osptrָ���Ƿ���ȷ��ָ���̡�������ʾ������Ϣ��
112 if (task[i]->p_ysptr) {
113 if (task[i]->p_pptr != task[i]->p_ysptr->p_pptr)
114 printk(
115 "Warning, pid %d younger sibling %d parent is %d\n",
116 task[i]->pid, task[i]->p_osptr->pid,
117 task[i]->p_osptr->p_pptr->pid);
118 if (task[i]->p_ysptr->p_osptr != task[i])
119 printk(
120 "Warning, pid %d younger sibling %d has mismatched os link\n",
121 task[i]->pid, task[i]->p_ysptr->pid);
122 }
// �������������ӽ���ָ��cptr���գ���ô�����ӽ��̵ĸ������Ƿ��DZ����̣�������
// �ӽ��̵�С�ܽ���ָ��yspter�Ƿ�Ϊ�ա�����������ʾ������Ϣ��
123 if (task[i]->p_cptr) {
124 if (task[i]->p_cptr->p_pptr != task[i])
125 printk(
126 "Warning, pid %d youngest child %d has mismatched parent link\n",
127 task[i]->pid, task[i]->p_cptr->pid);
128 if (task[i]->p_cptr->p_ysptr)
129 printk(
130 "Warning, pid %d youngest child %d has non-NULL ys link\n",
131 task[i]->pid, task[i]->p_cptr->pid);
132 }
133 }
134 }
135 #endif /* DEBUG_PROC_TREE */
136
//// ��ָ������p�����ź�sig��Ȩ��Ϊpriv��
// ������sig - �ź�ֵ��p - ָ�������ָ�룻priv - ǿ�Ʒ����źŵı�־��������Ҫ���ǽ���
// �û����Ի���ܷ����źŵ�Ȩ�����ú��������жϲ�������ȷ�ԣ�Ȼ���ж������Ƿ����㡣
// ����������ָ�����̷����ź�sig���˳�������δ���ɴ���š�
137 static inline int send_sig(long sig,struct task_struct * p,int priv)
138 {
// ���û��Ȩ�ޣ����ҵ�ǰ���̵���Ч�û�ID�����p�IJ�ͬ������Ҳ���dz����û�����˵��
// û����p�����źŵ�Ȩ����suser()����Ϊ(current->euid==0)�������ж��Ƿ��dz����û���
139 if (!p)
140 return -EINVAL;
141 if (!priv && (current->euid!=p->euid) && !suser())
142 return -EPERM;
// ����Ҫ���͵��ź���SIGKILL�� SIGCONT����ô�����ʱ�����źŵĽ��� p������ֹͣ״̬
// ������Ϊ���������У�״̬��Ȼ���Ľ���p���ź�λͼsignal��ȥ������λ���ᵼ�½���
// ֹͣ���ź�SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU��
143 if ((sig == SIGKILL) || (sig == SIGCONT)) {
144 if (p->state == TASK_STOPPED)
145 p->state = TASK_RUNNING;
146 p->exit_code = 0;
147 p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
148 (1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
149 }
150 /* If the signal will be ignored, don't even post it */
/* ���Ҫ���͵��ź�sig��������p���Ե�����ô�������÷��� */
151 if ((int) p->sigaction[sig-1].sa_handler == 1)
152 return 0;
153 /* Depends on order SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU */
/* �����ж�������SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU�Ĵ��� */
// ����ź���SIGSTOP��SIGTSTP��SIGTTIN��SIGTTOU֮һ����ô˵��Ҫ�ý����źŵĽ���p
// ֹͣ���С���ˣ���p ���ź�λͼ���� SIGCONT ��λ������Ҫ��λλͼ�м������е��ź�
// SIGCONT�����
154 if ((sig >= SIGSTOP) && (sig <= SIGTTOU))
155 p->signal &= ~(1<<(SIGCONT-1));
156 /* Actually deliver the signal */
/* ������������p�����ź�p */
157 p->signal |= (1<<(sig-1));
158 return 0;
159 }
160
// ���ݽ������pgrpȡ�ý����������ĻỰ�š�
// ɨ���������飬Ѱ�ҽ������Ϊpgrp�Ľ��̣���������Ự�š����û���ҵ�ָ���������
// Ϊpgrp���κν��̣���-1��
161 int session_of_pgrp(int pgrp)
162 {
163 struct task_struct **p;
164
165 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
166 if ((*p)->pgrp == pgrp)
167 return((*p)->session);
168 return -1;
169 }
170
// ��ֹ�����飨������鷢���źţ���
// ������pgrp - ָ���Ľ�����ţ�sig - ָ�����źţ�priv - Ȩ�ޡ�
// ����ָ��������pgrp�е�ÿ�����̷���ָ���ź�sig��ֻҪ��һ�����̷��ͳɹ����ͻ�
// ����0���������û���ҵ�ָ���������pgrp���κ�һ�����̣��س�����-ESRCH����
// �ҵ����������pgrp�Ľ��̣����Ƿ����ź�ʧ�ܣ��ط���ʧ�ܵĴ����롣
171 int kill_pg(int pgrp, int sig, int priv)
172 {
173 struct task_struct **p;
174 int err,retval = -ESRCH; // -ESRCH��ʾָ���Ľ��̲����ڡ�
175 int found = 0;
176
// �����жϸ������źźͽ�������Ƿ���Ч��Ȼ��ɨ��ϵͳ������������ɨ�赽�������Ϊ
// pgrp�Ľ��̣������䷢���ź�sig��ֻҪ��һ���źŷ��ͳɹ����������ͻ᷵��0��
177 if (sig<1 || sig>32 || pgrp<=0)
178 return -EINVAL;
179 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
180 if ((*p)->pgrp == pgrp) {
181 if (sig && (err = send_sig(sig,*p,priv)))
182 retval = err;
183 else
184 found++;
185 }
186 return(found ? 0 : retval);
187 }
188
// ��ֹ���̣�����̷����źţ���
// ������pid - ���̺ţ�sig - ָ���źţ�priv - Ȩ�ޡ�
// ������̺�Ϊpid�Ľ��̷���ָ���ź�sig�����ҵ�ָ��pid�Ľ��̣���ô���źŷ��ͳɹ���
// ��0�������źŷ��ͳ����š����û���ҵ�ָ�����̺�pid�Ľ��̣��س�����
// -ESRCH��ָ�����̲����ڣ���
189 int kill_proc(int pid, int sig, int priv)
190 {
191 struct task_struct **p;
192
193 if (sig<1 || sig>32)
194 return -EINVAL;
195 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
196 if ((*p)->pid == pid)
197 return(sig ? send_sig(sig,*p,priv) : 0);
198 return(-ESRCH);
199 }
200
201 /*
202 * POSIX specifies that kill(-1,sig) is unspecified, but what we have
203 * is probably wrong. Should make it like BSD or SYSV.
204 */
/*
* POSIX��ָ��kill(-1,sig)δ���塣��������֪���Ŀ��ܴ��ˡ�Ӧ������
* ��BSD��SYSVϵͳһ����
*/
//// ϵͳ����kill()���������κν��̻�����鷢���κ��źţ�������ֻ��ɱ������J��
// ����pid�ǽ��̺ţ�sig����Ҫ���͵��źš�
// ���pidֵ>0�����źű��������̺���pid�Ľ��̡�
// ���pid=0����ô�źžͻᱻ������ǰ���̵Ľ����������еĽ��̡�
// ���pid=-1�����ź�sig�ͻᷢ������һ�����̣���ʼ���̣�������н��̡�
// ���pid < -1�����ź�sig������������-pid�����н��̡�
// ����ź�sigΪ0�������źţ����Ի���д����顣����ɹ���0��
// �ú���ɨ�������������������pid�����������Ľ��̷���ָ���ź�sig����pid����0��
// ������ǰ�����ǽ������鳤�������Ҫ���������ڵĽ���ǿ�Ʒ����ź�sig��
205 int sys_kill(int pid,int sig)
206 {
207 struct task_struct **p = NR_TASKS + task; // pָ�������������һ�
208 int err, retval = 0;
209
210 if (!pid)
211 return(kill_pg(current->pid,sig,0));
212 if (pid == -1) {
213 while (--p > &FIRST_TASK)
214 if (err = send_sig(sig,*p,0))
215 retval = err;
216 return(retval);
217 }
218 if (pid < 0)
219 return(kill_pg(-pid,sig,0));
220 /* Normal kill */
221 return(kill_proc(pid,sig,0));
222 }
223
224 /*
225 * Determine if a process group is "orphaned", according to the POSIX
226 * definition in 2.2.2.52. Orphaned process groups are not to be affected
227 * by terminal-generated stop signals. Newly orphaned process groups are
228 * to receive a SIGHUP and a SIGCONT.
229 *
230 * "I ask you, have you ever known what it is to be an orphan?"
231 */
/*
* ����POSIX��2.2.2.52���еĶ��壬ȷ��һ���������Ƿ��ǡ��¶������¶�����
* �鲻���ܵ��ն˲�����ֹͣ�źŵ�Ӱ�졣�½������Ŷ������齫���յ�һ��SIGHUP
* �źź�һ��SIGCONT�źš�
*
* �������㣬���Ƿ�����֪����Ϊһ���¶���ζ��ʲô����
*/
// �����ᵽ��POSIX P1003.1 2.2.2.52���ǹ��ڹ¶������������������������µ�һ������
// ��ֹʱ���ܵ��½������ɡ��¶����� һ�������鵽������ĸ�����֮�����ϵ�����ڸø�
// ���̺����ӽ������ߡ���ˣ����������һ�����Ӹ����̵Ľ��̻����һ�������̵�ֱ�Ӻ���
// ��ֹ�Ļ�����ô���������ͻ��Ϊһ���¶������顣���κ�һ������£�������̵���ֹ��
// �½������ɹ¶������飬��ô�������е����н��̾ͻ������ǵ���ҵ����shell�Ͽ���ϵ��
// ��ҵ����shell�����پ��иý�������ڵ��κ���Ϣ�����ý������д���ֹͣ״̬�Ľ��̽���
// ��Զ��ʧ��Ϊ�˽��������⣬����ֹͣ״̬���̵��½������Ŷ����������Ҫ���յ�һ��
// SIGHUP�źź�һ��SIGCONT�źţ�����ָʾ�����Ѿ������ǵĻỰ�� session���жϿ���ϵ��
// SIGHUP�źŽ����½������г�Ա����ֹ���������Dz���������SIGHUP�źš��� SIGCONT��
// �Ž�ʹ��Щû�б�SIGHUP�ź���ֹ�Ľ��̼������С� ���ڴ��������£����������һ����
// �̴���ֹͣ״̬����ô�������еĽ��̿��ܶ�����ֹͣ״̬��
//
// �ж�һ���������Ƿ��ǹ¶����̡����������0���������1��
// ɨ���������顣���������գ����߽��̵������ָ���IJ�ͬ�����߽����Ѿ����ڽ���״̬��
// ���߽��̵ĸ�������init���̣���˵��ɨ��Ľ��̲���ָ��������ij�Ա�����߲�����Ҫ��
// ���������� ����˵���ý�����ָ����ij�Ա�����丸���̲��� init���̡���ʱ����ý���
// �����̵���Ų�����ָ�������pgrp���������̵ĻỰ�ŵ��ڽ��̵ĻỰ�ţ���˵������ͬ
// ����һ���Ự�����ָ����pgrp������϶����ǹ¶������顣����...��
232 int is_orphaned_pgrp(int pgrp)
233 {
234 struct task_struct **p;
235
236 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
237 if (!(*p) ||
238 ((*p)->pgrp != pgrp) ||
239 ((*p)->state == TASK_ZOMBIE) ||
240 ((*p)->p_pptr->pid == 1))
241 continue;
242 if (((*p)->p_pptr->pgrp != pgrp) &&
243 ((*p)->p_pptr->session == (*p)->session))
244 return 0;
245 }
246 return(1); /* (sighing) "Often!" */ /* �������ǹ¶������飡*/
247 }
248
// �жϽ��������Ƿ��д���ֹͣ״̬����ҵ�������飩������1������0��
// ���ҷ�����ɨ�������������顣�������ָ����pgrp���κν����Ƿ���ֹͣ״̬��
249 static int has_stopped_jobs(int pgrp)
250 {
251 struct task_struct ** p;
252
253 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
254 if ((*p)->pgrp != pgrp)
255 continue;
256 if ((*p)->state == TASK_STOPPED)
257 return(1);
258 }
259 return(0);
260 }
261
// �����˳�����������������365�д���ϵͳ���ô�������sys_exit()���á�
// �ú��������ݵ�ǰ�������������Զ�����д��������ѵ�ǰ����״̬���óɽ���״̬
// TASK_ZOMBIE�������õ��Ⱥ���schedule()ȥִ���������̣����ٷ��ء�
262 volatile void do_exit(long code)
263 {
264 struct task_struct *p;
265 int i;
266
// �����ͷŵ�ǰ���̴���κ����ݶ���ռ���ڴ�ҳ�� ����free_page_tables() �ĵ�1������
// ��get_base()����ֵ��ָ����CPU���Ե�ַ�ռ�����ʼ����ַ����2����get_limit()����ֵ��
// ˵�����ͷŵ��ֽڳ���ֵ��get_base()���е�current->ldt[1]�������̴������������λ��
// ��current->ldt[2]�������̴������������λ�ã���get_limit()�е�0x0f�ǽ��̴���ε�
// ѡ�����0x17�ǽ������ݶε�ѡ�����������ȡ�λ���ַʱʹ�øöε�������������ַ��Ϊ
// ������ȡ�γ���ʱʹ�øöε�ѡ�����Ϊ������ free_page_tables()����λ��mm/memory.c
// �ļ��ĵ�69�п�ʼ����get_base()��get_limit()��λ��include/linux/sched.hͷ�ļ��ĵ�
// 264�п�ʼ����
267 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
268 free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
// Ȼ��رյ�ǰ���̴��ŵ������ļ����ٶԵ�ǰ���̵Ĺ���Ŀ¼pwd����Ŀ¼root��ִ�г���
// �ļ��� i�ڵ��Լ����ļ�����ͬ���������Żظ��� i�ڵ㲢�ֱ��ÿգ��ͷţ��� ���Űѵ�ǰ
// ���̵�״̬����Ϊ����״̬��TASK_ZOMBIE���������ý����˳��롣
269 for (i=0 ; i<NR_OPEN ; i++)
270 if (current->filp[i])
271 sys_close(i);
272 iput(current->pwd);
273 current->pwd = NULL;
274 iput(current->root);
275 current->root = NULL;
276 iput(current->executable);
277 current->executable = NULL;
278 iput(current->library);
279 current->library = NULL;
280 current->state = TASK_ZOMBIE;
281 current->exit_code = code;
282 /*
283 * Check to see if any process groups have become orphaned
284 * as a result of our exiting, and if they have any stopped
285 * jobs, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
286 *
287 * Case i: Our father is in a different pgrp than we are
288 * and we were the only connection outside, so our pgrp
289 * is about to become orphaned.
290 */
/*
* ��鵱ǰ���̵��˳��Ƿ������κν������ɹ¶������顣���
* �У������д���ֹͣ״̬��TASK_STOPPED������Ա���������Ƿ���
* һ��SIGHUP�źź�һ��SIGCONT�źš���POSIX 3.2.2.2��Ҫ��
*
* ���1�����ǵĸ�����������һ�������Dz�ͬ�Ľ������У���������
* ������������Ψһ��ϵ���������ǵĽ����齫���һ���¶������顣
*/
// POSIX 3.2.2.2��1991�棩�ǹ���exit()������˵����������������ڵĽ������뵱ǰ���̵�
// ��ͬ����������ͬһ���Ự��session���У����ҵ�ǰ�������ڽ����齫Ҫ��ɹ¶������˲���
// ��ǰ���̵Ľ������к��д���ֹͣ״̬����ҵ�����̣�����ô��Ҫ�������ǰ���̵Ľ����鷢
// �������źţ�SIGHUP��SIGCONT�������������źŵ�ԭ���232��ǰ��˵����
291 if ((current->p_pptr->pgrp != current->pgrp) &&
292 (current->p_pptr->session == current->session) &&
293 is_orphaned_pgrp(current->pgrp) &&
294 has_stopped_jobs(current->pgrp)) {
295 kill_pg(current->pgrp,SIGHUP,1);
296 kill_pg(current->pgrp,SIGCONT,1);
297 }
298 /* Let father know we died */ /* ֪ͨ�����̵�ǰ���̽���ֹ */
299 current->p_pptr->signal |= (1<<(SIGCHLD-1));
300
301 /*
302 * This loop does two things:
303 *
304 * A. Make init inherit all the child processes
305 * B. Check to see if any process groups have become orphaned
306 * as a result of our exiting, and if they have any stopped
307 * jons, send them a SIGUP and then a SIGCONT. (POSIX 3.2.2.2)
308 */
/*
* �����ѭ�������������飺
*
* A. ��init���̼̳е�ǰ���������ӽ��̡�
* B. ��鵱ǰ���̵��˳��Ƿ������κν������ɹ¶������顣���
* �У������д���ֹͣ״̬��TASK_STOPPED������Ա���������Ƿ���
* һ��SIGHUP�źź�һ��SIGCONT�źš���POSIX 3.2.2.2��Ҫ��
*/
// �����ǰ�������ӽ��̣���p_cptrָ��ָ������������ӽ��̣������ý���1��init���̣�
// ��Ϊ�������ӽ��̵ĸ����̡�����ӽ����Ѿ����ڽ���״̬������init���̣������̣�����
// �ӽ�������ֹ�ź�SIGCHLD��
309 if (p = current->p_cptr) {
310 while (1) {
311 p->p_pptr = task[1];
312 if (p->state == TASK_ZOMBIE)
313 task[1]->signal |= (1<<(SIGCHLD-1));
314 /*
315 * process group orphan check
316 * Case ii: Our child is in a different pgrp
317 * than we are, and it was the only connection
318 * outside, so the child pgrp is now orphaned.
319 */
/* �¶��������⡣
* ���2�����ǵ��ӽ����ڲ�ͬ�Ľ������У���������
* ������Ψһ���������ӡ���������ӽ������ڽ���
* �齫��ɹ¶��������ˡ�
*/
// ����ӽ����뵱ǰ���̲���ͬһ���������е�����ͬһ��session�У����ҵ�ǰ�������ڽ���
// �齫Ҫ��ɹ¶������ˣ����ҵ�ǰ���̵Ľ������к��д���ֹͣ״̬����ҵ�����̣�����ô��
// Ҫ�������ǰ���̵Ľ����鷢�������źţ�SIGHUP��SIGCONT�� ������ӽ������ֵܽ��̣�
// �����ѭ��������Щ�ֵܽ��̡�
320 if ((p->pgrp != current->pgrp) &&
321 (p->session == current->session) &&
322 is_orphaned_pgrp(p->pgrp) &&
323 has_stopped_jobs(p->pgrp)) {
324 kill_pg(p->pgrp,SIGHUP,1);
325 kill_pg(p->pgrp,SIGCONT,1);
326 }
327 if (p->p_osptr) {
328 p = p->p_osptr;
329 continue;
330 }
331 /*
332 * This is it; link everything into init's children
333 * and leave
334 */
/*
* ���������������ӽ������ӳ�Ϊinit���ӽ��̲��˳�ѭ����
*/
// ͨ�����洦������ǰ�����ӽ��̵������ֵ��ӽ��̶��Ѿ�����������ʱpָ�����ϵ��ֵ���
// ���̡����ǰ���Щ�ֵ��ӽ���ȫ������init���̵��ӽ���˫������ͷ���С������init
// ���̵�p_cptr ָ��ǰ����ԭ�ӽ�����������ģ�the youngest���ӽ��̣���ԭ�ӽ�����
// ���ϵģ�the oldest���ֵ��ӽ��� p_osptr ָ��ԭ init���̵���������̣���ԭinit��
// ������������̵� p_ysptrָ��ԭ�ӽ��������ϵ��ֵ��ӽ��̡����ѵ�ǰ���̵�p_cptr
// ָ���ÿգ����˳�ѭ����
335 p->p_osptr = task[1]->p_cptr;
336 task[1]->p_cptr->p_ysptr = p;
337 task[1]->p_cptr = current->p_cptr;
338 current->p_cptr = 0;
339 break;
340 }
341 }
// �����ǰ�����ǻỰͷ��(leader)���̣���ô�����п����նˣ���������ʹ�øÿ����ն˵�
// �����鷢�Ҷ��ź�SIGHUP��Ȼ���ͷŸ��նˡ�����ɨ���������飬�����ڵ�ǰ���̻Ự��
// ���̵��ն��ÿգ�ȡ������
342 if (current->leader) {
343 struct task_struct **p;
344 struct tty_struct *tty;
345
346 if (current->tty >= 0) {
347 tty = TTY_TABLE(current->tty);
348 if (tty->pgrp>0)
349 kill_pg(tty->pgrp, SIGHUP, 1);
350 tty->pgrp = 0;
351 tty->session = 0;
352 }
353 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p)
354 if ((*p)->session == current->session)
355 (*p)->tty = -1;
356 }
// �����ǰ�����ϴ�ʹ�ù�Э����������Ѽ�¼����Ϣ��ָ���ÿա��������˵��Խ��������ţ�
// ����ý����������ʾ�����������õ��Ⱥ��������µ��Ƚ������У����ø������ܹ�����
// �������̵������ƺ����ˡ�
357 if (last_task_used_math == current)
358 last_task_used_math = NULL;
359 #ifdef DEBUG_PROC_TREE
360 audit_ptree();
361 #endif
362 schedule();
363 }
364
// ϵͳ����exit()����ֹ���̡�
// ����error_code���û������ṩ���˳�״̬��Ϣ��ֻ�е��ֽ���Ч����error_code����8
// ������ wait() �� waitpid()������Ҫ���ֽ��н���������wait()��״̬��Ϣ�����磬
// ������̴�����ͣ״̬��TASK_STOPPED������ô����ֽھ͵��� 0x7f���μ� sys/wait.h
// �ļ���13--19�С� wait() ��waitpid() ������Щ��Ϳ���ȡ���ӽ��̵��˳�״̬�����
// ������ֹ��ԭ���źţ���
365 int sys_exit(int error_code)
366 {
367 do_exit((error_code&0xff)<<8);
368 }
369
// ϵͳ����waitpid()������ǰ���̣�ֱ��pid ָ�����ӽ����˳�����ֹ�������յ�Ҫ����ֹ
// �ý��̵��źţ���������Ҫ����һ���źž�����źŴ����������pid��ָ���ӽ�������
// �˳����ѳ���ν�Ľ������̣������ý����̷��ء��ӽ���ʹ�õ�������Դ���ͷš�
// ���pid > 0����ʾ�ȴ����̺ŵ���pid���ӽ��̡�
// ���pid = 0����ʾ�ȴ�������ŵ��ڵ�ǰ������ŵ��κ��ӽ��̡�
// ���pid < -1����ʾ�ȴ�������ŵ���pid����ֵ���κ��ӽ��̡�
// ���pid = -1����ʾ�ȴ��κ��ӽ��̡�
// ��options = WUNTRACED����ʾ����ӽ�����ֹͣ�ģ�Ҳ���Ϸ��أ�������٣���
// ��options = WNOHANG����ʾ���û���ӽ����˳�����ֹ�����Ϸ��ء�
// �������״ָ̬��stat_addr��Ϊ�գ���ͽ�״̬��Ϣ���浽���
// ����pid�ǽ��̺ţ�*stat_addr�DZ���״̬��Ϣλ�õ�ָ�룻options��waitpidѡ�
370 int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
371 {
372 int flag; // �ñ�־���ں����ʾ��ѡ�����ӽ��̴��ھ�����˯��̬��
373 struct task_struct *p;
374 unsigned long oldblocked;
375
// ������֤��Ҫ���״̬��Ϣ��λ�ô��ڴ�ռ��㹻��Ȼ��λ��־flag�����Ŵӵ�ǰ���̵���
// �����ӽ��̿�ʼɨ���ӽ����ֵ�������
376 verify_area(stat_addr,4);
377 repeat:
378 flag=0;
379 for (p = current->p_cptr ; p ; p = p->p_osptr) {
// ����ȴ����ӽ��̺�pid>0�����뱻ɨ���ӽ���p��pid����ȣ�˵�����ǵ�ǰ�����������
// ���̣����������ý��̣�����ɨ����һ�����̡�
380 if (pid>0) {
381 if (p->pid != pid)
382 continue;
// �������ָ���ȴ����̵�pid=0����ʾ���ڵȴ�������ŵ��ڵ�ǰ������ŵ��κ��ӽ��̡�
// �����ʱ��ɨ�����p�Ľ�������뵱ǰ���̵���Ų��ȣ���������
383 } else if (!pid) {
384 if (p->pgrp != current->pgrp)
385 continue;
// �������ָ����pid < -1����ʾ���ڵȴ�������ŵ���pid����ֵ���κ��ӽ��̡������ʱ
// ��ɨ�����p�������pid�ľ���ֵ���ȣ���������
386 } else if (pid != -1) {
387 if (p->pgrp != -pid)
388 continue;
389 }
// ���ǰ3����pid���ж϶������ϣ����ʾ��ǰ�������ڵȴ����κ��ӽ��̣�Ҳ��pid = -1
// ���������ʱ��ѡ�Ľ��� p ����������̺ŵ���ָ�� pid�������ǵ�ǰ�������е��κ�
// �ӽ��̣������ǽ��̺ŵ���ָ�� pid ����ֵ���ӽ��̣��������κ��ӽ��̣���ʱָ���� pid
// ���� -1������������������ӽ���p������״̬��������
// ���ӽ���p ����ֹͣ״̬ʱ�������ʱ����ѡ��options��WUNTRACED ��־û����λ����ʾ
// �����������̷��أ������ӽ��̴�ʱ���˳������ 0�����Ǽ���ɨ�账�������ӽ��̡� ���
// WUNTRACED��λ���ӽ����˳��벻Ϊ0������˳���������ֽڣ�����״̬��Ϣ 0x7f �����
// *stat_addr���ڸ�λ�ӽ����˳��������̷����ӽ��̺�pid������0x7f ��ʾ�ķ���״̬ʹ
// WIFSTOPPED()��Ϊ�档�μ�include/sys/wait.h��14�С�
390 switch (p->state) {
391 case TASK_STOPPED:
392 if (!(options & WUNTRACED) ||
393 !p->exit_code)
394 continue;
395 put_fs_long((p->exit_code << 8) | 0x7f,
396 stat_addr);
397 p->exit_code = 0;
398 return p->pid;
// ����ӽ���p���ڽ���״̬�������Ȱ������û�̬���ں�̬���е�ʱ��ֱ��ۼƵ���ǰ����
// �������̣��У�Ȼ��ȡ���ӽ��̵�pid���˳��룬���˳�����뷵��״̬λ��stat_addr��
// ���ͷŸ��ӽ��̡�����ӽ��̵��˳����pid�� �������˵��Խ��������ţ�����ý���
// �������ʾ������
399 case TASK_ZOMBIE:
400 current->cutime += p->utime;
401 current->cstime += p->stime;
402 flag = p->pid;
403 put_fs_long(p->exit_code, stat_addr);
404 release(p);
405 #ifdef DEBUG_PROC_TREE
406 audit_ptree();
407 #endif
408 return flag;
// �������ӽ���p��״̬�Ȳ���ֹͣҲ���ǽ�������ô����flag = 1����ʾ�ҵ���һ������
// Ҫ����ӽ��̣���������������̬��˯��̬��
409 default:
410 flag=1;
411 continue;
412 }
413 }
// ���������������ɨ���������� flag����λ��˵���з��ϵȴ�Ҫ����ӽ��̲�û�д�
// ���˳�����״̬����ʱ���������WNOHANGѡ���ʾ��û���ӽ��̴����˳�����ֹ̬��
// ���̷��أ��������̷���0���˳�������ѵ�ǰ������Ϊ���жϵȴ�״̬������������
// ��ǰ�����ź�����λͼ����������յ�SIGCHLD�źš�Ȼ��ִ�е��ȳ���ϵͳ�ֿ�ʼ
// ִ�б�����ʱ������������յ���SIGCHLD���������δ�����źţ������˳��롰������
// ��ϵͳ���á����ء�������ת��������ʼ��repeat��Ŵ��ظ�������
414 if (flag) {
415 if (options & WNOHANG)
416 return 0;
417 current->state=TASK_INTERRUPTIBLE;
418 oldblocked = current->blocked;
419 current->blocked &= ~(1<<(SIGCHLD-1));
420 schedule();
421 current->blocked = oldblocked;
422 if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1))))
423 return -ERESTARTSYS;
424 else
425 goto repeat;
426 }
// ��flag = 0����ʾû���ҵ�����Ҫ����ӽ��̣��س����루�ӽ��̲����ڣ���
427 return -ECHILD;
428 }
429
1 /*
2 * linux/kernel/fork.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'fork.c' contains the help-routines for the 'fork' system call
9 * (see also system_call.s), and some misc functions ('verify_area').
10 * Fork is rather simple, once you get the hang of it, but the memory
11 * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'
12 */
/*
* 'fork.c'�к���ϵͳ����'fork'�ĸ����ӳ��μ�system_call.s�����Լ�һЩ
* ����������'verify_area'����һ�����˽���fork���ͻᷢ�����Ƿdz��ģ���
* �ڴ����ȴ��Щ�Ѷȡ��μ�'mm/memory.c'�е�'copy_page_tables()'������
*/
13 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
14
15 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݡ�
16 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
17 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
18 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
19
// дҳ����֤����ҳ�治��д������ҳ�档������mm/memory.c ��261�п�ʼ��
20 extern void write_verify(unsigned long address);
21
22 long last_pid=0; // ���½��̺ţ���ֵ����get_empty_process()���ɡ�
23
//// ���̿ռ�����дǰ��֤������
// ����80386 CPU����ִ����Ȩ��0����ʱ���������û��ռ��е�ҳ���Ƿ���ҳ�����ģ����
// ��ִ���ں˴���ʱ�û��ռ�������ҳ�汣����־�������ã�дʱ���ƻ���Ҳ��ʧȥ�����á�
// verify_area()���������ڴ�Ŀ�ġ�������80486�������CPU������ƼĴ���CR0����һ��
// д������־WP��λ16�����ں˿���ͨ�����øñ�־����ֹ��Ȩ��0�Ĵ������û��ռ�ֻ��
// ҳ��ִ��д���ݣ������·���д�����쳣���Ӷ�486����CPU����ͨ�����øñ�־����
// ��ʹ�ñ�����ͬ����Ŀ�ġ�
// �ú����Ե�ǰ��������ַ�� addr �� addr + size ��һ�η�Χ��ҳΪ��λִ��д����ǰ
// �ļ����������ڼ���ж�����ҳ��Ϊ��λ���в�������˳���������Ҫ�ҳ�addr����ҳ
// �濪ʼ��ַstart��Ȼ�� start���Ͻ������ݶλ�ַ��ʹ���start�任��CPU 4G���Կ�
// ���еĵ�ַ�����ѭ������write_verify() ��ָ����С���ڴ�ռ����дǰ��֤����ҳ��
// ��ֻ���ģ���ִ�й����������ҳ�������дʱ���ƣ���
24 void verify_area(void * addr,int size)
25 {
26 unsigned long start;
27
// ���Ƚ���ʼ��ַstart����Ϊ������ҳ����߽翪ʼλ�ã�ͬʱ��Ӧ�ص�����֤�����С��
// �¾��е� start & 0xfff �������ָ����ʼλ��addr��Ҳ��start��������ҳ���е�ƫ��
// ֵ��ԭ��֤��Χ size �������ƫ��ֵ����չ���� addr ����ҳ����ʼλ�ÿ�ʼ�ķ�Χֵ��
// ����� 30���� Ҳ��Ҫ����֤��ʼλ�� start ������ҳ��߽�ֵ���μ�ǰ���ͼ���ڴ���
// ֤��Χ�ĵ�������
28 start = (unsigned long) addr;
29 size += start & 0xfff;
30 start &= 0xfffff000; // ��ʱstart�ǵ�ǰ���̿ռ��е�����ַ��
// ����� start ���Ͻ������ݶ������Ե�ַ�ռ��е���ʼ��ַ�����ϵͳ�������Կռ��еĵ�
// ַλ�á�����Linux 0.1x�ںˣ������ݶκʹ���������Ե�ַ�ռ��еĻ�ַ��������ͬ��
// Ȼ��ѭ������дҳ����֤����ҳ�治��д������ҳ�档��mm/memory.c��274�У�
31 start += get_base(current->ldt[2]); // include/linux/sched.h��277��
32 while (size>0) {
33 size -= 4096;
34 write_verify(start);
35 start += 4096;
36 }
37 }
38
// �����ڴ�ҳ����
// ����nr��������ţ�p�����������ݽṹָ�롣�ú���Ϊ�����������Ե�ַ�ռ������ô���
// �κ����ݶλ�ַ������������ҳ���� ����Linuxϵͳ������дʱ���ƣ�copy on write��
// ������ ��������Ϊ�½��������Լ���ҳĿ¼�����ҳ�����û��ʵ��Ϊ�½��̷�������
// �ڴ�ҳ�档��ʱ�½������丸���̹��������ڴ�ҳ�档�����ɹ�����0�����س����š�
39 int copy_mem(int nr,struct task_struct * p)
40 {
41 unsigned long old_data_base,new_data_base,data_limit;
42 unsigned long old_code_base,new_code_base,code_limit;
43
// ����ȡ��ǰ���ֲ̾����������д���������������ݶ����������еĶ������ֽ�������
// 0x0f�Ǵ����ѡ�����0x17�����ݶ�ѡ�����Ȼ��ȡ��ǰ���̴���κ����ݶ������Ե�ַ
// �ռ��еĻ���ַ������Linux 0.12�ں˻���֧�ִ�������ݶη�������������������Ҫ
// ������κ����ݶλ�ַ�Ƿ���ͬ������Ҫ�����ݶεij������ٲ�С�ڴ���εij���
// ���μ�ͼ5-12���������ں���ʾ������Ϣ����ֹͣ���С�
// get_limit()��get_base()������include/linux/sched.h��277�к�279�д���
44 code_limit=get_limit(0x0f);
45 data_limit=get_limit(0x17);
46 old_code_base = get_base(current->ldt[1]);
47 old_data_base = get_base(current->ldt[2]);
48 if (old_data_base != old_code_base)
49 panic("We don't support separate I&D");
50 if (data_limit < code_limit)
51 panic("Bad data_limit");
// Ȼ�����ô����е��½��������Ե�ַ�ռ��еĻ���ַ���ڣ�64MB * ������ţ������ø�ֵ
// �����½��ֲ̾����������ж��������еĻ���ַ�����������½��̵�ҳĿ¼�����ҳ���
// �����Ƶ�ǰ���̣������̣���ҳĿ¼�����ҳ��� ��ʱ�ӽ��̹��������̵��ڴ�ҳ�档
// ���������copy_page_tables()����0�������ʾ���������ͷŸ������ҳ���
52 new_data_base = new_code_base = nr * TASK_SIZE;
53 p->start_code = new_code_base;
54 set_base(p->ldt[1],new_code_base);
55 set_base(p->ldt[2],new_data_base);
56 if (copy_page_tables(old_data_base,new_data_base,data_limit)) {
57 free_page_tables(new_data_base,data_limit);
58 return -ENOMEM;
59 }
60 return 0;
61 }
62
63 /*
64 * Ok, this is the main fork-routine. It copies the system process
65 * information (task[nr]) and sets up the necessary registers. It
66 * also copies the data segment in it's entirety.
67 */
/*
* OK����������Ҫ��fork�ӳ���������ϵͳ������Ϣ(task[n])
* �������ñ�Ҫ�ļĴ��������������ظ������ݶΣ�Ҳ�Ǵ���Σ���
*/
// ���ƽ��̡�
// �ú����IJ����ǽ���ϵͳ�����жϴ������̣�sys_call.s����ʼ��ֱ�����ñ�ϵͳ���ô���
// ���̣�sys_call.s��208�У��͵��ñ�����ǰ��sys_call.s��217�У���ѹ������ں�
// ̬ջ�ĸ��Ĵ�����ֵ����Щ��sys_call.s��������ѹ���ں�̬ջ��ֵ������������:
// �� CPUִ���ж�ָ��ѹ����û�ջ��ַss��esp����־eflags�ͷ��ص�ַcs��eip��
// �� ��83--88���ڸս���system_callʱ��ջ�ĶμĴ���ds��es��fs��edx��ecx��edx��
// �� ��94�е���sys_call_table��sys_fork����ʱ��ջ�ķ��ص�ַ������none��ʾ����
// �� ��212--216���ڵ���copy_process()֮ǰ��ջ��gs��esi��edi��ebp��eax��nr����
// ���в���nr�ǵ���find_empty_process()���������������š�
68 int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,
69 long ebx,long ecx,long edx, long orig_eax,
70 long fs,long es,long ds,
71 long eip,long cs,long eflags,long esp,long ss)
72 {
73 struct task_struct *p;
74 int i;
75 struct file *f;
76
// ����Ϊ���������ݽṹ�����ڴ档����ڴ����������س����벢�˳���Ȼ��������
// �ṹָ��������������nr���С�����nrΪ����ţ���ǰ��find_empty_process()���ء�
// ���Űѵ�ǰ��������ṹ���ݸ��Ƶ������뵽���ڴ�ҳ��p��ʼ����
77 p = (struct task_struct *) get_free_page();
78 if (!p)
79 return -EAGAIN;
80 task[nr] = p;
81 *p = *current; /* NOTE! this doesn't copy the supervisor stack */
/* ע�⣡���������Ḵ�Ƴ����û���ջ��ֻ���ƽ��̽ṹ��*/
// ���Ը������Ľ��̽ṹ���ݽ���һЩ�ģ���Ϊ�½��̵�����ṹ���Ƚ��½��̵�״̬
// ��Ϊ�����жϵȴ�״̬���Է�ֹ�ں˵�����ִ�С�Ȼ�������½��̵Ľ��̺�pid������ʼ
// ����������ʱ��Ƭֵ������ priorityֵ�� һ��Ϊ15����ણ������Ÿ�λ�½��̵��ź�
// λͼ��������ʱֵ���Ự��session���쵼��־ leader�� ���̼����ӽ������ں˺��û�
// ̬����ʱ��ͳ��ֵ�������ý��̿�ʼ���е�ϵͳʱ��start_time��
82 p->state = TASK_UNINTERRUPTIBLE;
83 p->pid = last_pid; // �½��̺š�Ҳ��find_empty_process()�õ���
84 p->counter = p->priority; // ����ʱ��Ƭֵ�����������
85 p->signal = 0; // �ź�λͼ��
86 p->alarm = 0; // ������ʱֵ�����������
87 p->leader = 0; /* process leadership doesn't inherit */
/* ���̵��쵼Ȩ�Dz��ܼ̳е� */
88 p->utime = p->stime = 0; // �û�̬ʱ��ͺ���̬����ʱ�䡣
89 p->cutime = p->cstime = 0; // �ӽ����û�̬�ͺ���̬����ʱ�䡣
90 p->start_time = jiffies; // ���̿�ʼ����ʱ�䣨��ǰʱ��δ�������
// ��������״̬��TSS ���ݣ��μ��б���˵����������ϵͳ������ṹ p������1ҳ��
// �ڴ棬���� (PAGE_SIZE + (long) p) ��esp0����ָ���ҳ���ˡ� ss0:esp0 ��������
// ���ں�ִ̬��ʱ��ջ�����⣬�ڵ�3���������Ѿ�֪����ÿ�������� GDT���ж�������
// ����������һ���������TSS������������һ���������LDT����������������111��
// �����ǰ�GDT�б�����LDT����������ѡ��������ڱ������TSS���С���CPUִ��
// �л�����ʱ�����Զ���TSS�а�LDT����������ѡ������ص�ldtr�Ĵ����С�
91 p->tss.back_link = 0;
92 p->tss.esp0 = PAGE_SIZE + (long) p; // �����ں�̬ջָ�롣
93 p->tss.ss0 = 0x10; // �ں�̬ջ�Ķ�ѡ��������ں����ݶ���ͬ����
94 p->tss.eip = eip; // ָ�����ָ�롣
95 p->tss.eflags = eflags; // ��־�Ĵ�����
96 p->tss.eax = 0; // ���ǵ�fork()����ʱ�½��̻᷵��0��ԭ�����ڡ�
97 p->tss.ecx = ecx;
98 p->tss.edx = edx;
99 p->tss.ebx = ebx;
100 p->tss.esp = esp;
101 p->tss.ebp = ebp;
102 p->tss.esi = esi;
103 p->tss.edi = edi;
104 p->tss.es = es & 0xffff; // �μĴ�����16λ��Ч��
105 p->tss.cs = cs & 0xffff;
106 p->tss.ss = ss & 0xffff;
107 p->tss.ds = ds & 0xffff;
108 p->tss.fs = fs & 0xffff;
109 p->tss.gs = gs & 0xffff;
110 p->tss.ldt = _LDT(nr); // ����ֲ�����������ѡ�����LDT��������GDT�У���
111 p->tss.trace_bitmap = 0x80000000; //����16λ��Ч����
// �����ǰ����ʹ����Э���������ͱ����������ġ����ָ��clts����������ƼĴ���CR0
// �е������ѽ�����TS����־��ÿ�����������л���CPU�������øñ�־���ñ�־���ڹ���
// ��ѧЭ������������ñ�־��λ����ôÿ��ESCָ��ᱻ�����쳣7�������Э����
// �����ڱ�־MPҲͬʱ��λ�Ļ�����ôWAITָ��Ҳ�Ჶ����ˣ���������л�������һ
// ��ESCָ�ʼִ��֮����Э�������е����ݾͿ�����Ҫ��ִ���µ�ESCָ��֮ǰ����
// ����������������ᱣ��Э�����������ݲ���λTS��־��ָ��fnsave���ڰ�Э������
// ������״̬���浽Ŀ�IJ�����ָ�����ڴ������У�tss.i387����
112 if (last_task_used_math == current)
113 __asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));
// ���������ƽ���ҳ�����������Ե�ַ�ռ����������������κ����ݶ��������еĻ�ַ
// ������������ҳ�����������������ֵ����0������λ������������Ӧ��ͷ�Ϊ
// ��������������������ṹ���ڴ�ҳ��
114 if (copy_mem(nr,p)) { // ���ز�Ϊ0��ʾ������
115 task[nr] = NULL;
116 free_page((long) p);
117 return -EAGAIN;
118 }
// ��������������ļ��Ǵģ���Ӧ�ļ��Ĵ�����1����Ϊ���ﴴ�����ӽ���
// ���븸���̹�����Щ���ļ�������ǰ���̣������̣���pwd, root��executable
// ���ô�������1��������ͬ���ĵ������ӽ���Ҳ��������Щi�ڵ㡣
119 for (i=0; i<NR_OPEN;i++)
120 if (f=p->filp[i])
121 f->f_count++;
122 if (current->pwd)
123 current->pwd->i_count++;
124 if (current->root)
125 current->root->i_count++;
126 if (current->executable)
127 current->executable->i_count++;
128 if (current->library)
129 current->library->i_count++;
// �����GDT��������������TSS�κ�LDT����������������ε����������ó�104
// �ֽڡ��μ� include/asm/system.h��52��66 �д��롣 Ȼ�����ý���֮��Ĺ�ϵ����
// ָ�룬�����½��̲��뵽��ǰ���̵��ӽ��������С����½��̵ĸ���������Ϊ��ǰ���̣�
// ���½��̵������ӽ���ָ��p_cptr �������ֵܽ���ָ��p_ysptr�ÿա��������½���
// �����ֽ���ָ��p_osptr���õ��ڸ����̵������ӽ���ָ�롣����ǰ����ȴ�ǻ�������
// �ӽ��̣����ñ������ֽ��̵����������ָ��p_yspter ָ���½��̡����ѵ�ǰ����
// �������ӽ���ָ��ָ������½��̡�Ȼ����½������óɾ���̬������½��̺š�
// ���⣬ set_tss_desc() �� set_ldt_desc() ������ include/asm/system.h �ļ��С�
// ��gdt+(nr<<1)+FIRST_TSS_ENTRY��������nr��TSS����������ȫ�ֱ��еĵ�ַ����Ϊ
// ÿ������ռ��GDT����2������ʽ��Ҫ����'(nr<<1)'��
// ��ע�⣬�������л�ʱ������Ĵ���tr����CPU�Զ����ء�
130 set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));
131 set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));
132 p->p_pptr = current; // �����½��̵ĸ�����ָ�롣
133 p->p_cptr = 0; // ��λ�½��̵������ӽ���ָ�롣
134 p->p_ysptr = 0; // ��λ�½��̵ı��������ֵܽ���ָ�롣
135 p->p_osptr = current->p_cptr; // �����½��̵ı��������ֵܽ���ָ�롣
136 if (p->p_osptr) // ���½����������ֵܽ��̣�������
137 p->p_osptr->p_ysptr = p; // ��������ֵ�ָ��ָ���½��̡�
138 current->p_cptr = p; // �õ�ǰ���������ӽ���ָ��ָ���½��̡�
139 p->state = TASK_RUNNING; /* do this last, just in case */
140 return last_pid;
141 }
142
// Ϊ�½���ȡ�ò��ظ��Ľ��̺�last_pid���������������������е������(������)��
143 int find_empty_process(void)
144 {
145 int i;
146
// ���Ȼ�ȡ�µĽ��̺š����last_pid��1�����̺ŵ�������ʾ��Χ�������´�1��ʼ
// ʹ��pid�š� Ȼ�����������������������õ�pid���Ƿ��Ѿ����κ�����ʹ�á��������
// ��ת��������ʼ�����»��һ��pid�š� ����������������Ϊ������Ѱ��һ���������
// ������š� last_pid��һ��ȫ�ֱ��������÷��ء������ʱ����������64�����Ѿ���ȫ
// ��ռ�ã��س����롣
147 repeat:
148 if ((++last_pid)<0) last_pid=1;
149 for(i=0 ; i<NR_TASKS ; i++)
150 if (task[i] && ((task[i]->pid == last_pid) ||
151 (task[i]->pgrp == last_pid)))
152 goto repeat;
153 for(i=1 ; i<NR_TASKS ; i++) // ����0��ų����⡣
154 if (!task[i])
155 return i;
156 return -EAGAIN;
157 }
158
1 /*
2 * linux/kernel/sys.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8
9 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
10 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <linux/config.h> // �ں˳��������ļ���������Ҫʹ�����е�ϵͳ���Ƴ���������Ϣ��
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14 #include <sys/times.h> // �����˽���������ʱ��Ľṹtms�Լ�times()����ԭ�͡�
15 #include <sys/utsname.h> // ϵͳ���ƽṹͷ�ļ���
16 #include <sys/param.h> // ϵͳ����ͷ�ļ�������ϵͳһЩȫ�ֳ������š�����HZ�ȡ�
17 #include <sys/resource.h> // ϵͳ��Դͷ�ļ��������йؽ�����Դʹ������Ľṹ����Ϣ��
18 #include <string.h> // �ַ���ͷ�ļ����ַ������ڴ��ֽ����в���������
19
20 /*
21 * The timezone where the local system is located. Used as a default by some
22 * programs who obtain this value by using gettimeofday.
23 */
/*
* ��ϵͳ���ڵ�ʱ����timezone������ΪijЩ����ʹ��gettimeofdayϵͳ���û�ȡ
* ʱ����Ĭ��ֵ��
*/
// ʱ���ṹtimezone��1���ֶΣ�tz_minuteswest����ʾ��������α�ʱ��GMT�����ķ���
// ������2���ֶΣ�tz_dsttime��������ʱDST��Daylight Savings Time���������͡� �ýṹ
// ������include/sys/time.h��
24 struct timezone sys_tz = { 0, 0};
25
// ���ݽ������pgrpȡ�ý����������Ự��session���š��ú�����kernel/exit.c��ʵ�֡�
26 extern int session_of_pgrp(int pgrp);
27
// �������ں�ʱ�䣨ftime �C Fetch time����
// ���·���ֵ��-ENOSYS��ϵͳ���ú�������ʾ�ڱ��汾�ں��л�δʵ�֡�
28 int sys_ftime()
29 {
30 return -ENOSYS;
31 }
32
33 int sys_break()
34 {
35 return -ENOSYS;
36 }
37
// ���ڵ�ǰ���̶��ӽ��̽��е���(debugging)��
38 int sys_ptrace()
39 {
40 return -ENOSYS;
41 }
42
// �ı䲢��ӡ�ն������á�
43 int sys_stty()
44 {
45 return -ENOSYS;
46 }
47
// ȡ�ն���������Ϣ��
48 int sys_gtty()
49 {
50 return -ENOSYS;
51 }
52
// �������
53 int sys_rename()
54 {
55 return -ENOSYS;
56 }
57
58 int sys_prof()
59 {
60 return -ENOSYS;
61 }
62
63 /*
64 * This is done BSD-style, with no consideration of the saved gid, except
65 * that if you set the effective gid, it sets the saved gid too. This
66 * makes it possible for a setgid program to completely drop its privileges,
67 * which is often a useful assertion to make when you are doing a security
68 * audit over a program.
69 *
70 * The general idea is that a program which uses just setregid() will be
71 * 100% compatible with BSD. A program which uses just setgid() will be
72 * 100% compatible with POSIX w/ Saved ID's.
73 */
/*
* ������BSD��ʽ��ʵ�֣�û�п��DZ����gid��saved gid��sgid�������˵���
* ��������Ч��gid��effective gid��egid��ʱ�������gidҲ�ᱻ���á���ʹ
* ��һ��ʹ��setgid�ij��������ȫ��������Ȩ�������ڶ�һ��������а�ȫ��
* ��ʱ����ͨ����һ�ֺܺõĴ���������
*
* ������Ŀ�����һ��ʹ��setregid()�ij�����BSDϵͳ100%�ļ��ݡ���һ
* ��ʹ��setgid()�ͱ����gid�ij�����POSIX 100%�ļ��ݡ�
*/
// ���õ�ǰ�����ʵ���Լ�/������Ч��ID��gid�����������û�г����û���Ȩ����ôֻ�ܻ�
// ����ʵ����ID ����Ч�� ID�����������г����û���Ȩ����������������Ч�ĺ�ʵ�ʵ���
// ID��������gid��saved gid�������ó�����Чgid��ʵ����ID��ָ���̵�ǰ��gid��
74 int sys_setregid(int rgid, int egid)
75 {
76 if (rgid>0) {
77 if ((current->gid == rgid) ||
78 suser())
79 current->gid = rgid;
80 else
81 return(-EPERM);
82 }
83 if (egid>0) {
84 if ((current->gid == egid) ||
85 (current->egid == egid) ||
86 suser()) {
87 current->egid = egid;
88 current->sgid = egid;
89 } else
90 return(-EPERM);
91 }
92 return 0;
93 }
94
95 /*
96 * setgid() is implemeneted like SysV w/ SAVED_IDS
97 */
/*
* setgid()��ʵ�������SAVED_IDS��SYSV��ʵ�ַ������ơ�
*/
// ���ý������(gid)���������û�г����û���Ȩ��������ʹ�� setgid() ������Чgid
// ��effective gid������Ϊ���䱣��gid(saved gid)����ʵ��gid(real gid)���������
// �г����û���Ȩ����ʵ��gid����Чgid�ͱ���gid�������óɲ���ָ����gid��
98 int sys_setgid(int gid)
99 {
100 if (suser())
101 current->gid = current->egid = current->sgid = gid;
102 else if ((gid == current->gid) || (gid == current->sgid))
103 current->egid = gid;
104 else
105 return -EPERM;
106 return 0;
107 }
108
// ��رս��̼��ʹ��ܡ�
109 int sys_acct()
110 {
111 return -ENOSYS;
112 }
113
// ӳ�����������ڴ浽���̵������ַ�ռ䡣
114 int sys_phys()
115 {
116 return -ENOSYS;
117 }
118
119 int sys_lock()
120 {
121 return -ENOSYS;
122 }
123
124 int sys_mpx()
125 {
126 return -ENOSYS;
127 }
128
129 int sys_ulimit()
130 {
131 return -ENOSYS;
132 }
133
// ���ش� 1970��1��1��00:00:00 GMT ��ʼ��ʱ��ʱ��ֵ���룩�����tloc��Ϊnull��
// ��ʱ��ֵҲ�洢�����
// ���ڲ�����һ��ָ�룬������ָλ�����û��ռ䣬�����Ҫʹ�ú��� put_fs_long() ��
// ���ʸ�ֵ���ڽ����ں�������ʱ���μĴ���fs��Ĭ�ϵ�ָ��ǰ�û����ݿռ䡣��˸�
// �����Ϳ�����fs�������û��ռ��е�ֵ��
134 int sys_time(long * tloc)
135 {
136 int i;
137
138 i = CURRENT_TIME;
139 if (tloc) {
140 verify_area(tloc,4); // ��֤�ڴ������Ƿ�������4�ֽڣ���
141 put_fs_long(i,(unsigned long *)tloc); // �����û����ݶ�tloc����
142 }
143 return i;
144 }
145
146 /*
147 * Unprivileged users may change the real user id to the effective uid
148 * or vice versa. (BSD-style)
149 *
150 * When you set the effective uid, it sets the saved uid too. This
151 * makes it possible for a setuid program to completely drop its privileges,
152 * which is often a useful assertion to make when you are doing a security
153 * audit over a program.
154 *
155 * The general idea is that a program which uses just setreuid() will be
156 * 100% compatible with BSD. A program which uses just setuid() will be
157 * 100% compatible with POSIX w/ Saved ID's.
158 */
/*
* ����Ȩ���û����Լ�ʵ�ʵ�uid��real uid���ij���Ч��uid��effective uid����
* ��֮ҲȻ����BSD��ʽ��ʵ�֣�
*
* ����������Ч��uid ʱ����ͬʱҲ�����˱���� uid����ʹ��һ��ʹ�� setuid
* �ij��������ȫ��������Ȩ�������ڶ�һ��������а�ȫ���ʱ����ͨ����һ��
* �ܺõĴ���������
* ������Ŀ�����һ��ʹ�� setreuid()�ij����� BSDϵͳ100%�ļ��ݡ���һ
* ��ʹ��setuid()�ͱ����gid�ij�����POSIX 100%�ļ��ݡ�
*/
// ���������ʵ���Լ�/������Ч���û�ID��uid�����������û�г����û���Ȩ����ôֻ��
// ������ʵ�ʵ�uid ����Ч��uid�����������г����û���Ȩ����������������Ч�ĺ�ʵ
// �ʵ��û�ID�������uid��saved uid�������ó�����Чuidֵͬ��
159 int sys_setreuid(int ruid, int euid)
160 {
161 int old_ruid = current->uid;
162
163 if (ruid>0) {
164 if ((current->euid==ruid) ||
165 (old_ruid == ruid) ||
166 suser())
167 current->uid = ruid;
168 else
169 return(-EPERM);
170 }
171 if (euid>0) {
172 if ((old_ruid == euid) ||
173 (current->euid == euid) ||
174 suser()) {
175 current->euid = euid;
176 current->suid = euid;
177 } else {
178 current->uid = old_ruid;
179 return(-EPERM);
180 }
181 }
182 return 0;
183 }
184
185 /*
186 * setuid() is implemeneted like SysV w/ SAVED_IDS
187 *
188 * Note that SAVED_ID's is deficient in that a setuid root program
189 * like sendmail, for example, cannot set its uid to be a normal
190 * user and then switch back, because if you're root, setuid() sets
191 * the saved uid too. If you don't like this, blame the bright people
192 * in the POSIX commmittee and/or USG. Note that the BSD-style setreuid()
193 * will allow a root program to temporarily drop privileges and be able to
194 * regain them by swapping the real and effective uid.
195 */
/*
* setuid()��ʵ�������SAVED_IDS��SYSV��ʵ�ַ������ơ�
*
* ��ע��ʹ��SAVED_ID��setuid()��ijЩ�����Dz����Ƶġ����磬һ��ʹ��
* setuid�ij����û�����sendmail������������uid���ó�һ����ͨ�û���
* uid��Ȼ���ٽ��������� ��Ϊ�������һ�������û���setuid() Ҳͬʱ��
* ���ñ����uid������㲻ϲ�������������Ļ��������POSIX��ί���Լ�
* /����USG�еĴ����˰ɡ�������ע��BSD��ʽ��setreuid()ʵ���ܹ�����
* һ�������û�������ʱ������Ȩ��������ͨ������ʵ�ʵĺ���Ч�� uid ��
* �ٴλ����Ȩ��
*/
// ���������û�ID��uid�����������û�г����û���Ȩ��������ʹ��setuid()������Ч��
// uid��effective uid�����ó��䱣���uid��saved uid������ʵ�ʵ�uid��real uid����
// ��������г����û���Ȩ����ʵ�ʵ�uid����Ч��uid�ͱ����uid���ᱻ���óɲ���ָ
// ����uid��
196 int sys_setuid(int uid)
197 {
198 if (suser())
199 current->uid = current->euid = current->suid = uid;
200 else if ((uid == current->uid) || (uid == current->suid))
201 current->euid = uid;
202 else
203 return -EPERM;
204 return(0);
205 }
206
// ����ϵͳ����ʱ�䡣����tptr�Ǵ�1970��1��1��00:00:00 GMT��ʼ��ʱ��ʱ��ֵ���룩��
// ���ý��̱�����г����û�Ȩ�ޡ�����HZ=100�����ں�ϵͳ����Ƶ�ʡ�
// ���ڲ�����һ��ָ�룬������ָλ�����û��ռ䣬�����Ҫʹ�ú���get_fs_long()�����ʸ�
// ֵ���ڽ����ں�������ʱ���μĴ��� fs ��Ĭ�ϵ�ָ��ǰ�û����ݿռ䡣��˸ú����Ϳ���
// ��fs�������û��ռ��е�ֵ��
// ���������ṩ�ĵ�ǰʱ��ֵ��ȥϵͳ�Ѿ����е�ʱ����ֵ��jiffies/HZ�����ǿ���ʱ����ֵ��
207 int sys_stime(long * tptr)
208 {
209 if (!suser()) // ������dz����û���������أ����ɣ���
210 return -EPERM;
211 startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
212 jiffies_offset = 0;
213 return 0;
214 }
215
// ��ȡ��ǰ��������ʱ��ͳ��ֵ��
// ��tbuf��ָ�û����ݿռ䴦����tms�ṹ����������ʱ��ͳ��ֵ��tms�ṹ�а��������û�
// ����ʱ�䡢�ںˣ�ϵͳ��ʱ�䡢�ӽ����û�����ʱ�䡢�ӽ���ϵͳ����ʱ�䡣��������ֵ��
// ϵͳ���е���ǰ���������
216 int sys_times(struct tms * tbuf)
217 {
218 if (tbuf) {
219 verify_area(tbuf,sizeof *tbuf);
220 put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
221 put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
222 put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
223 put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
224 }
225 return jiffies;
226 }
227
// ������end_data_seg��ֵ����������ϵͳȷʵ���㹻���ڴ棬���ҽ���û�г�Խ���������
// �δ�Сʱ���ú����������ݶ�ĩβΪend_data_segָ����ֵ����ֵ������ڴ����β����Ҫ
// С�ڶ�ջ��β16KB������ֵ�����ݶε��½�βֵ���������ֵ��Ҫ��ֵ��ͬ��������д���
// ���������ú����������û�ֱ�ӵ��ã�����libc�⺯�����а�װ�����ҷ���ֵҲ��һ����
228 int sys_brk(unsigned long end_data_seg)
229 {
// �������ֵ���ڴ����β������С�ڣ���ջ - 16KB���������������ݶν�βֵ��
230 if (end_data_seg >= current->end_code &&
231 end_data_seg < current->start_stack - 16384)
232 current->brk = end_data_seg;
233 return current->brk; // ���ؽ��̵�ǰ�����ݶν�βֵ��
234 }
235
236 /*
237 * This needs some heave checking ...
238 * I just haven't get the stomach for it. I also don't fully
239 * understand sessions/pgrp etc. Let somebody who does explain it.
240 *
241 * OK, I think I have the protection semantics right.... this is really
242 * only important on a multi-user system anyway, to make sure one user
243 * can't send a signal to a process owned by another. -TYT, 12/12/91
244 */
/*
* ���������ҪijЩ�ϸ�ļ����
* ��ֻ��û��θ��������Щ����Ҳ����ȫ����sessions/pgrp�ȵĺ��塣������
* �˽����ǵ��������ɡ�
*
* OK���������Ѿ���ȷ��ʵ���˱�������...����֮������ʵֻ�Զ��û�ϵͳ��
* ��Ҫ�ģ���ȷ��һ���û������������û��Ľ��̷����źš� -TYT 12/12/91
*/
// ����ָ������pid�Ľ������Ϊpgid��
// ����pid ��ָ�����̵Ľ��̺š������Ϊ0������pid���ڵ�ǰ���̵Ľ��̺š�����pgid
// ��ָ���Ľ�����š������Ϊ0�����������ڽ���pid�Ľ�����š�����ú������ڽ�����
// ��һ���������Ƶ���һ�������飬���������������������ͬһ���Ự(session)��������
// ����£�����pgid ָ����Ҫ��������н�����ID����ʱ����ĻỰID�����뽫Ҫ�����
// �̵���ͬ(263��)��
245 int sys_setpgid(int pid, int pgid)
246 {
247 int i;
248
// �������pidΪ0����pidȡֵΪ��ǰ���̵Ľ��̺�pid���������pgidΪ0����pgidҲ
// ȡֵΪ��ǰ���̵�pid��[?? ������POSIX���������г��� ]���� pgidС��0����
// ��Ч�����롣
249 if (!pid)
250 pid = current->pid;
251 if (!pgid)
252 pgid = current->pid;
253 if (pgid < 0)
254 return -EINVAL;
// ɨ���������飬����ָ�����̺� pid ����������ҵ��˽��̺���pid �Ľ��̣����Ҹý���
// �ĸ����̾��ǵ�ǰ���̻��߸ý��̾��ǵ�ǰ���̣���ô���������Ѿ��ǻỰ���죬��������ء�
// ��������ĻỰ�ţ�session���뵱ǰ���̵IJ�ͬ������ָ���Ľ������pgid��pid��ͬ����
// pgid �����������Ự���뵱ǰ���������Ự�Ų�ͬ����Ҳ�������ء� ����Ѳ��ҵ��Ľ��̵�
// pgrp����Ϊpgid��������0����û���ҵ�ָ��pid�Ľ��̣��ؽ��̲����ڳ����롣
255 for (i=0 ; i<NR_TASKS ; i++)
256 if (task[i] && (task[i]->pid == pid) &&
257 ((task[i]->p_pptr == current) ||
258 (task[i] == current))) {
259 if (task[i]->leader)
260 return -EPERM;
261 if ((task[i]->session != current->session) ||
262 ((pgid != pid) &&
263 (session_of_pgrp(pgid) != current->session)))
264 return -EPERM;
265 task[i]->pgrp = pgid;
266 return 0;
267 }
268 return -ESRCH;
269 }
270
// ���ص�ǰ���̵Ľ�����š���getpgid(0)��ͬ��
271 int sys_getpgrp(void)
272 {
273 return current->pgrp;
274 }
275
// ����һ���Ự(session)����������leader=1��������������Ự��=�����=����̺š�
// �����ǰ�������ǻỰ���첢�Ҳ��dz����û�����������ء��������õ�ǰ����Ϊ�»Ự
// ���죨leader = 1�����������õ�ǰ���̻Ự�� session�����pgrp�����ڽ��̺�pid��
// �������õ�ǰ����û�п����նˡ����ϵͳ���÷��ػỰ�š�
276 int sys_setsid(void)
277 {
278 if (current->leader && !suser())
279 return -EPERM;
280 current->leader = 1;
281 current->session = current->pgrp = current->pid;
282 current->tty = -1; // ��ʾ��ǰ����û�п����նˡ�
283 return current->pgrp;
284 }
285
286 /*
287 * Supplementary group ID's
288 */
/*
* ���̵������û���š�
*/
// ȡ��ǰ�������������û���š�
// �������ݽṹ��groups[]���鱣���Ž���ͬʱ�����Ķ���û���š������鹲NGROUPS���
// ��ij���ֵ��NOGROUP����Ϊ -1�������ʾ�Ӹ��ʼ�Ժ���������С������������б�
// ������û���š�
// ����gidsetsize�ǻ�ȡ���û���Ÿ�����grouplist�Ǵ洢��Щ�û���ŵ��û��ռ仺�档
289 int sys_getgroups(int gidsetsize, gid_t *grouplist)
290 {
291 int i;
292
// ������֤grouplistָ����ָ���û�����ռ��Ƿ��㹻��Ȼ��ӵ�ǰ���̽ṹ��groups[]
// ���������ȡ���û���Ų����Ƶ��û������С��ڸ��ƹ����У���� groups[] �е�����
// ���ڸ����IJ��� gidsetsize ��ָ���ĸ��������ʾ�û������Ļ���̫С���������µ�ǰ
// ����������ţ���˴˴�ȡ��Ų�����������ء������ƹ����������������᷵�ظ�
// �Ƶ��û���Ÿ�������gidsetsize �C gid set size���û���ż���С����
293 if (gidsetsize)
294 verify_area(grouplist, sizeof(gid_t) * gidsetsize);
295
296 for (i = 0; (i < NGROUPS) && (current->groups[i] != NOGROUP);
297 i++, grouplist++) {
298 if (gidsetsize) {
299 if (i >= gidsetsize)
300 return -EINVAL;
301 put_fs_word(current->groups[i], (short *) grouplist);
302 }
303 }
304 return(i); // ����ʵ�ʺ��е��û���Ÿ�����
305 }
306
// ���õ�ǰ����ͬʱ���������������û���š�
// ����gidsetsize�ǽ����õ��û���Ÿ�����grouplist�Ǻ����û���ŵ��û��ռ仺�档
307 int sys_setgroups(int gidsetsize, gid_t *grouplist)
308 {
309 int i;
310
// ���Ȳ�Ȩ�Ͳ�������Ч�ԡ�ֻ�г����û������Ļ����õ�ǰ���̵ĸ����û���ţ�����
// ���õ��������ܳ������̵�groups[NGROUPS]�����������Ȼ����û���������������û�
// ��ţ���gidsetsize����������Ƶĸ���û������groups[]���������һ��������ֵΪ-1
// ���NOGROUP�������������0��
311 if (!suser())
312 return -EPERM;
313 if (gidsetsize > NGROUPS)
314 return -EINVAL;
315 for (i = 0; i < gidsetsize; i++, grouplist++) {
316 current->groups[i] = get_fs_word((unsigned short *) grouplist);
317 }
318 if (i < NGROUPS)
319 current->groups[i] = NOGROUP;
320 return 0;
321 }
322
// ��鵱ǰ�����Ƿ���ָ�����û���grp�С�����1������0��
323 int in_group_p(gid_t grp)
324 {
325 int i;
326
// �����ǰ���̵���Ч��ž���grp�����ʾ��������grp�����顣��������1���������
// ���̵ĸ����û���������ɨ���Ƿ��� grp ������š���������Ҳ����1����ɨ�赽ֵ
// Ϊ NOGROUP �����ʾ��ɨ����ȫ����Ч���û�з���ƥ�����ţ���˺�������0��
327 if (grp == current->egid)
328 return 1;
329
330 for (i = 0; i < NGROUPS; i++) {
331 if (current->groups[i] == NOGROUP)
332 break;
333 if (current->groups[i] == grp)
334 return 1;
335 }
336 return 0;
337 }
338
// utsname�ṹ����һЩ�ַ����ֶΡ����ڱ���ϵͳ�����ơ����а���5���ֶΣ��ֱ��ǣ�
// ��ǰ����ϵͳ�����ơ�����ڵ����ƣ�������������ǰ����ϵͳ���м��𡢲���ϵͳ�汾
// ���Լ�ϵͳ���е�Ӳ���������ơ��ýṹ������ include/sys/utsname.h �ļ��С� ����
// �ں�ʹ�� include/linux/config.h �ļ��еij����������������ǵ�Ĭ��ֵ�����Ƿֱ�Ϊ
// ��Linux������(none)������0������0.12������i386����
339 static struct utsname thisname = {
340 UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, UTS_MACHINE
341 };
342
// ��ȡϵͳ���Ƶ���Ϣ��
343 int sys_uname(struct utsname * name)
344 {
345 int i;
346
347 if (!name) return -ERROR;
348 verify_area(name,sizeof *name);
349 for(i=0;i<sizeof *name;i++)
350 put_fs_byte(((char *) &thisname)[i],i+(char *) name);
351 return 0;
352 }
353
354 /*
355 * Only sethostname; gethostname can be implemented by calling uname()
356 */
/*
* ͨ������uname()ֻ��ʵ��sethostname��gethostname��
*/
// ����ϵͳ��������ϵͳ������ڵ�������
// ����nameָ��ָ���û��������к����������ַ����Ļ�������len���������ַ������ȡ�
357 int sys_sethostname(char *name, int len)
358 {
359 int i;
360
// ϵͳ������ֻ���ɳ����û����û��ģ��������������Ȳ��ܳ������MAXHOSTNAMELEN��
361 if (!suser())
362 return -EPERM;
363 if (len > MAXHOSTNAMELEN)
364 return -EINVAL;
365 for (i=0; i < len; i++) {
366 if ((thisname.nodename[i] = get_fs_byte(name+i)) == 0)
367 break;
368 }
// �ڸ�����Ϻ�����û��ṩ���ַ�����û�а���NULL�ַ�����ô�����Ƶ����������Ȼ�û��
// ���� MAXHOSTNAMELEN�������������ַ���������һ��NULL�����Ѿ����� MAXHOSTNAMELEN����
// ����������һ���ַ��ij�NULL�ַ�����thisname.nodename[min(i,MAXHOSTNAMELEN)] = 0��
369 if (thisname.nodename[i]) {
370 thisname.nodename[i>MAXHOSTNAMELEN ? MAXHOSTNAMELEN : i] = 0;
371 }
372 return 0;
373 }
374
// ȡ��ǰ����ָ����Դ�Ľ���ֵ��
// ���̵�����ṹ�ж�����һ������rlim[RLIM_NLIMITS]�����ڿ��ƽ���ʹ��ϵͳ��Դ�Ľ��ޡ�
// ����ÿ������һ��rlimit �ṹ�����а��������ֶΡ� һ��˵�����̶�ָ����Դ�ĵ�ǰ����
// ���ޣ�soft limit���������ƣ�����һ��˵��ϵͳ��ָ����Դ��������ƽ��ޣ�hard limit��
// ��Ӳ���ƣ��� rlim[] �����ÿһ���Ӧϵͳ�Ե�ǰ����һ����Դ�Ľ�����Ϣ��Linux 0.12
// ϵͳ����6����Դ�涨�˽��ޣ���RLIM_NLIMITS=6����ο�ͷ�ļ�include/sys/resource.h
// �е�41 �� 46�е�˵����
// ���� resource ָ��������ѯ����Դ���ƣ�ʵ������������ṹ��rlim[]�����������ֵ��
// ����rlim��ָ��rlimit�ṹ���û�������ָ�룬���ڴ��ȡ�õ���Դ������Ϣ��
375 int sys_getrlimit(int resource, struct rlimit *rlim)
376 {
// ����ѯ����Դresourceʵ�����ǽ�������ṹ��rlim[]�����������ֵ��������ֵ��Ȼ����
// ���������������� RLIM_NLIMITS������֤�� rlim ָ����ָ�û������㹻�Ժ�����Ͱ�
// ����ָ������Դresource�ṹ��Ϣ���Ƶ��û������У�������0��
377 if (resource >= RLIM_NLIMITS)
378 return -EINVAL;
379 verify_area(rlim,sizeof *rlim);
380 put_fs_long(current->rlim[resource].rlim_cur, // ��ǰ����������ֵ��
381 (unsigned long *) rlim);
382 put_fs_long(current->rlim[resource].rlim_max, // ϵͳ��Ӳ������ֵ��
383 ((unsigned long *) rlim)+1);
384 return 0;
385 }
386
// ���õ�ǰ����ָ����Դ�Ľ���ֵ��
// ���� resource ָ���������ý�����Դ���ƣ�ʵ������������ṹ��rlim[]���������
// ��ֵ������rlim��ָ��rlimit�ṹ���û�������ָ�룬�����ں˶�ȡ�µ���Դ������Ϣ��
387 int sys_setrlimit(int resource, struct rlimit *rlim)
388 {
389 struct rlimit new, *old;
390
// �����жϲ���resource������ṹrlim[]������ֵ����Ч�ԡ�Ȼ������rlimit�ṹָ��
// oldָ��ָ��������ṹ��ָ����Դ�ĵ�ǰrlimit�ṹ��Ϣ�����Ű��û��ṩ����Դ����
// ��Ϣ���Ƶ���ʱrlimit�ṹnew�С���ʱ����жϳ�new�ṹ�е�������ֵ��Ӳ����ֵ
// ���ڽ��̸���ԴԭӲ����ֵ�����ҵ�ǰ���dz����û��Ļ����ͷ������ɴ��������ʾnew
// ����Ϣ�������߽����dz����û����̣�����ԭ����ָ����Դ��Ϣ����new�ṹ�е���Ϣ��
// ���ɹ�����0��
391 if (resource >= RLIM_NLIMITS)
392 return -EINVAL;
393 old = current->rlim + resource; // ��old = current->rlim[resource]��
394 new.rlim_cur = get_fs_long((unsigned long *) rlim);
395 new.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
396 if (((new.rlim_cur > old->rlim_max) ||
397 (new.rlim_max > old->rlim_max)) &&
398 !suser())
399 return -EPERM;
400 *old = new;
401 return 0;
402 }
403
404 /*
405 * It would make sense to put struct rusuage in the task_struct,
406 * except that would make the task_struct be *really big*. After
407 * task_struct gets moved into malloc'ed memory, it would
408 * make sense to do this. It will make moving the rest of the information
409 * a lot simpler! (Which we're not doing right now because we're not
410 * measuring them yet).
411 */
/*
* ��rusuage�ṹ�Ž�����ṹtask struct����ǡ���ģ���������ʹ����
* �ṹ���ȱ�÷dz����ڰ�����ṹ�����ں�malloc������ڴ���֮��
* ��������ʹ����ṹ�ܴ�Ҳû�����ˡ��⽫ʹ��������Ϣ���ƶ���÷dz�
* ���㣡�����ǻ�û������������Ϊ���ǻ�û�в��Թ����ǵĴ�С����
*/
// ��ȡָ�����̵���Դ������Ϣ��
// ��ϵͳ�����ṩ��ǰ���̻�������ֹ�ĺ͵ȴ��ŵ��ӽ�����Դʹ��������������who����
// RUSAGE_SELF���ص�ǰ���̵���Դ������Ϣ�����ָ������who �� RUSAGE_CHILDREN��
// �ص�ǰ���̵�����ֹ�͵ȴ��ŵ��ӽ�����Դ������Ϣ�� ���ų���RUSAGE_SELF ��
// RUSAGE_CHILDREN �Լ� rusage�ṹ�������� include/sys/resource.hͷ�ļ��С�
412 int sys_getrusage(int who, struct rusage *ru)
413 {
414 struct rusage r;
415 unsigned long *lp, *lpend, *dest;
416
// �����жϲ���ָ�����̵���Ч�ԡ����who�Ȳ���RUSAGE_SELF��ָ����ǰ���̣���Ҳ����
// RUSAGE_CHILDREN ��ָ���ӽ��̣���������Ч�����뷵�ء���������֤��ָ��ru ָ������
// �������������ʱ rusage�ṹ����r���㡣
417 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
418 return -EINVAL;
419 verify_area(ru, sizeof *ru);
420 memset((char *) &r, 0, sizeof(r)); // ��include/strings.h����
// ������who ��RUSAGE_SELF�����Ƶ�ǰ������Դ������Ϣ��r�ṹ�С���ָ������who
// ��RUSAGE_CHILDREN�� ���Ƶ�ǰ���̵�����ֹ�͵ȴ��ŵ��ӽ�����Դ������Ϣ����ʱ
// rusuage�ṹr�С���CT_TO_SECS ��CT_TO_USECS���ڰ�ϵͳ��ǰ�����ת��������ֵ
// ����ֵ��ʾ�����Ƕ����� include/linux/sched.h �ļ��С� jiffies_offset��ϵͳ
// ���������������
421 if (who == RUSAGE_SELF) {
422 r.ru_utime.tv_sec = CT_TO_SECS(current->utime);
423 r.ru_utime.tv_usec = CT_TO_USECS(current->utime);
424 r.ru_stime.tv_sec = CT_TO_SECS(current->stime);
425 r.ru_stime.tv_usec = CT_TO_USECS(current->stime);
426 } else {
427 r.ru_utime.tv_sec = CT_TO_SECS(current->cutime);
428 r.ru_utime.tv_usec = CT_TO_USECS(current->cutime);
429 r.ru_stime.tv_sec = CT_TO_SECS(current->cstime);
430 r.ru_stime.tv_usec = CT_TO_USECS(current->cstime);
431 }
// Ȼ����lpָ��ָ��r�ṹ��lpendָ��r�ṹĩβ������destָ��ָ���û��ռ��е�ru
// �ṹ������r����Ϣ���Ƶ��û��ռ�ru�ṹ�У�������0��
432 lp = (unsigned long *) &r;
433 lpend = (unsigned long *) (&r+1);
434 dest = (unsigned long *) ru;
435 for (; lp < lpend; lp++, dest++)
436 put_fs_long(*lp, dest);
437 return(0);
438 }
439
// ȡ��ϵͳ��ǰʱ�䣬����ָ����ʽ���ء�
// timeval�ṹ��timezone�ṹ��������include/sys/time.h�ļ��С�timeval�ṹ������
// ���루tv_sec��tv_usec�������ֶΡ�timezone�ṹ���б��ؾ�������α�ʱ������
// �ķ�������tz_minuteswest��������ʱ��������ͣ�tz_dsttime�������ֶΡ�
// ��dst -- Daylight Savings Time��
440 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
441 {
// �������������timeval�ṹָ�벻�գ����ڸýṹ�з��ص�ǰʱ�䣨��ֵ����ֵ����
// ��������������û����ݿռ��� timezone�ṹ��ָ�벻�գ���Ҳ���ظýṹ����Ϣ��
// ������startup_time��ϵͳ����ʱ�䣨��ֵ���� ��CT_TO_SECS��CT_TO_USECS����
// ��ϵͳ��ǰ�����ת��������ֵ����ֵ��ʾ�����Ƕ�����include/linux/sched.h
// �ļ��С�jiffies_offset��ϵͳ���������������
442 if (tv) {
443 verify_area(tv, sizeof *tv);
444 put_fs_long(startup_time + CT_TO_SECS(jiffies+jiffies_offset),
445 (unsigned long *) tv);
446 put_fs_long(CT_TO_USECS(jiffies+jiffies_offset),
447 ((unsigned long *) tv)+1);
448 }
449 if (tz) {
450 verify_area(tz, sizeof *tz);
451 put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
452 put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
453 }
454 return 0;
455 }
456
457 /*
458 * The first time we set the timezone, we will warp the clock so that
459 * it is ticking GMT time instead of local time. Presumably,
460 * if someone is setting the timezone then we are running in an
461 * environment where the programs understand about timezones.
462 * This should be done at boot time in the /etc/rc script, as
463 * soon as possible, so that the clock can be set right. Otherwise,
464 * various programs will get confused when the clock gets warped.
465 */
/*
* �ڵ�1������ʱ����timezone��ʱ�����ǻ�ı�ʱ��ֵ����ϵͳʹ�ø���
* ���α�ʱ�䣨GMT�����У�����ʹ�ñ���ʱ�䡣 �Ʋ�����˵�����ij��
* ������ʱ��ʱ�䣬��ô���Ǿ������ڳ���֪��ʱ��ʱ��Ļ����С�����ʱ
* ������Ӧ����ϵͳ�����Σ��������/etc/rc�ű������н��С�����ʱ
* �ӾͿ���������ȷ�� ����Ļ����������Ժ������ʱ��������ʱ��ʱ��
* �ı䣬���ܻ���һЩ��������г������⡣
*/
// ����ϵͳ��ǰʱ�䡣
// ����tv��ָ���û���������timeval�ṹ��Ϣ��ָ�롣����tz���û���������timezone
// �ṹ��ָ�롣�ò�����Ҫ�����û�Ȩ�ޡ�������߽�Ϊ�գ���ʲôҲ��������������0��
466 int sys_settimeofday(struct timeval *tv, struct timezone *tz)
467 {
468 static int firsttime = 1;
469 void adjust_clock();
470
// ����ϵͳ��ǰʱ����Ҫ�����û�Ȩ�ޡ����tzָ�벻�գ�������ϵͳʱ����Ϣ���������û�
// timezone�ṹ��Ϣ��ϵͳ�е� sys_tz�ṹ�У�����24�У�������ǵ�1�ε��ñ�ϵͳ����
// ���Ҳ���tvָ�벻�գ������ϵͳʱ��ֵ��
471 if (!suser())
472 return -EPERM;
473 if (tz) {
474 sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
475 sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
476 if (firsttime) {
477 firsttime = 0;
478 if (!tv)
479 adjust_clock();
480 }
481 }
// ���������timeval�ṹָ��tv���գ����øýṹ��Ϣ����ϵͳʱ�ӡ����ȴ�tv��ָ��
// ��ȡ����ֵ��sec������ֵ��usec����ʾ��ϵͳʱ�䣬Ȼ������ֵ��ϵͳ����ʱ��ȫ��
// ����startup_timeֵ��������ֵ����ϵͳ������ֵjiffies_offset��
482 if (tv) {
483 int sec, usec;
484
485 sec = get_fs_long((unsigned long *)tv);
486 usec = get_fs_long(((unsigned long *)tv)+1);
487
488 startup_time = sec - jiffies/HZ;
489 jiffies_offset = usec * HZ / 1000000 - jiffies%HZ;
490 }
491 return 0;
492 }
493
494 /*
495 * Adjust the time obtained from the CMOS to be GMT time instead of
496 * local time.
497 *
498 * This is ugly, but preferable to the alternatives. Otherwise we
499 * would either need to write a program to do it in /etc/rc (and risk
500 * confusion if the program gets run more than once; it would also be
501 * hard to make the program warp the clock precisely n hours) or
502 * compile in the timezone information into the kernel. Bad, bad....
503 *
504 * XXX Currently does not adjust for daylight savings time. May not
505 * need to do anything, depending on how smart (dumb?) the BIOS
506 * is. Blast it all.... the best thing to do not depend on the CMOS
507 * clock at all, but get the time via NTP or timed if you're on a
508 * network.... - TYT, 1/1/92
509 */
/*
* �Ѵ�CMOS�ж�ȡ��ʱ��ֵ����ΪGMTʱ��ֵ���棬���DZ���ʱ��ֵ��
*
* ��������������ţ���Ҫ�����������á��������Ǿ���Ҫдһ����������
* ��/etc/rc��������������£�����ð�Ÿó�����ܻᱻ���ִ�ж�������
* ���⡣ ����������Ҳ�����ó����ʱ�Ӿ�ȷ�ص���nСʱ�� ���߰�ʱ����
* Ϣ������ں��С���Ȼ�������ͷdz����dz����...
*
* Ŀǰ���溯����XXX���ĵ���������û�п��ǵ�����ʱ���⡣����BIOS�ж�
* ô���ܣ�������Ҳ�������Ͳ��ÿ����ⷽ�档��Ȼ����õ���������ȫ��
* ������CMOSʱ�ӣ�������ϵͳͨ��NTP������ʱ��Э�飩����timed��ʱ��
* �����������ʱ�䣬��������������Ļ�...�� - TYT��1/1/92
*/
// ��ϵͳ����ʱ�����Ϊ��GMTΪ����ʱ�䡣
// startup_time����ֵ�����������Ҫ��ʱ������ֵ����60��
510 void adjust_clock()
511 {
512 startup_time += sys_tz.tz_minuteswest*60;
513 }
514
// ���õ�ǰ���̴����ļ�����������Ϊmask & 0777��������ԭ�����롣
515 int sys_umask(int mask)
516 {
517 int old = current->umask;
518
519 current->umask = mask & 0777;
520 return (old);
521 }
522
1 /*
2 * linux/kernel/vsprintf.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 */
// Lars Wirzenius��Linus�ĺ��ѣ���Helsinki��ѧʱ��ͬ��һ��칫�ҡ���1991���ļ�����Linux
// ʱ��Linus��ʱ��C���Ի����Ǻ���Ϥ��������ʹ�ÿɱ�����б��������ܡ����Lars Wirzenius
// ��Ϊ����д����������ں���ʾ��Ϣ�Ĵ��롣������(1998��)��������δ�������һ��bug��ֱ��
// 1994������˷��֣������Ծ��������bug����ʹ��*��Ϊ��������ʱ�����ǵ���ָ�����������
// ���ˡ��ڱ����������bug����Ȼ���ڣ�130�У��� ���ĸ�����ҳ��http://liw.iki.fi/liw/
11
12 #include <stdarg.h> // ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��
// ����(va_list)��������(va_start, va_arg��va_end)������
// vsprintf��vprintf��vfprintf������
13 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
14
15 /* we use this so that we can do without the ctype library */
/* ����ʹ������Ķ��壬�������ǾͿ��Բ�ʹ��ctype���� */
16 #define is_digit(c) ((c) >= '0' && (c) <= '9') // �ж��ַ�c�Ƿ�Ϊ�����ַ���
17
// �ú������ַ����ִ�ת�������������������ִ�ָ���ָ�룬�����ǽ����ֵ������ָ�뽫ǰ�ơ�
18 static int skip_atoi(const char **s)
19 {
20 int i=0;
21
22 while (is_digit(**s))
23 i = i*10 + *((*s)++) - '0';
24 return i;
25 }
26
// ���ﶨ��ת�����͵ĸ��ַ��ų�����
27 #define ZEROPAD 1 /* pad with zero */ /* ����� */
28 #define SIGN 2 /* unsigned/signed long */ /* ����/���ų����� */
29 #define PLUS 4 /* show plus */ /* ��ʾ�� */
30 #define SPACE 8 /* space if plus */ /* ���Ǽӣ����ÿո� */
31 #define LEFT 16 /* left justified */ /* ����� */
32 #define SPECIAL 32 /* 0x */ /* 0x */
33 #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ /* ʹ��Сд��ĸ */
34
// �����������룺nΪ��������baseΪ�����������nΪ�̣���������ֵΪ������
// �μ�4.5.3���й�Ƕ�������Ϣ��
35 #define do_div(n,base) ({ \
36 int __res; \
37 __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
38 __res; })
39
// ������ת��Ϊָ�����Ƶ��ַ�����
// ���룺num-������base-���ƣ�size-�ַ������ȣ�precision-���ֳ���(����)��type-����ѡ�
// ���������ת�����ַ�����ָ����ַ���ĩ�˺����ָ�롣
40 static char * number(char * str, int num, int base, int size, int precision
41 ,int type)
42 {
43 char c,sign,tmp[36];
44 const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
45 int i;
46
// �������typeָ����Сд��ĸ������Сд��ĸ����
// �������ָ��Ҫ�����������߽磩�������������е������־��
// ������ƻ���С��2�����36�����˳�������Ҳ��������ֻ�ܴ���������2-32֮�������
47 if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
48 if (type&LEFT) type &= ~ZEROPAD;
49 if (base<2 || base>36)
50 return 0;
// �������ָ��Ҫ���㣬�����ַ�����c='0'������c���ڿո��ַ���
// �������ָ���Ǵ�������������ֵnumС��0�����÷��ű���sign=���ţ���ʹnumȡ����ֵ��
// �����������ָ���ǼӺţ�����sign=�Ӻţ����������ʹ��ո��־��sign=�ո�����0��
51 c = (type & ZEROPAD) ? '0' : ' ' ;
52 if (type&SIGN && num<0) {
53 sign='-';
54 num = -num;
55 } else
56 sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
// �������ţ������ֵ��1��������ָ��������ת���������ʮ�����ƿ����ټ���2λ(����0x)��
// ���ڰ˽��ƿ��ȼ�1�����ڰ˽���ת�����ǰ��һ���㣩��
57 if (sign) size--;
58 if (type&SPECIAL)
59 if (base==16) size -= 2;
60 else if (base==8) size--;
// �����ֵnumΪ0������ʱ�ַ���='0'��������ݸ����Ļ�������ֵnumת�����ַ���ʽ��
61 i=0;
62 if (num==0)
63 tmp[i++]='0';
64 else while (num!=0)
65 tmp[i++]=digits[do_div(num,base)];
// ����ֵ�ַ��������ھ���ֵ����ֵ��չΪ���ָ���ֵ��
// ����ֵsize��ȥ���ڴ����ֵ�ַ��ĸ�����
66 if (i>precision) precision=i;
67 size -= precision;
// ������������ʼ�γ�����Ҫ��ת�����������ʱ�����ַ���str�С�
// ��������û������(ZEROPAD)�����루���������־������str������
// ���ʣ�����ֵָ���Ŀո��������������λ���������š�
68 if (!(type&(ZEROPAD+LEFT)))
69 while(size-->0)
70 *str++ = ' ';
71 if (sign)
72 *str++ = sign;
// ������ָ��������ת��������ڰ˽���ת�����ͷһλ����һ��'0'��������ʮ����������'0x'��
73 if (type&SPECIAL)
74 if (base==8)
75 *str++ = '0';
76 else if (base==16) {
77 *str++ = '0';
78 *str++ = digits[33]; // 'X'��'x'
79 }
// ��������û������������룩��־������ʣ������д��c�ַ���'0'��ո���51�С�
80 if (!(type&LEFT))
81 while(size-->0)
82 *str++ = c;
// ��ʱi������ֵnum�����ָ����������ָ���С�ھ���ֵ����str�з��루����ֵ-i����'0'��
83 while(i<precision--)
84 *str++ = '0';
// ����ֵת���õ������ַ�����str�С���i����
85 while(i-->0)
86 *str++ = tmp[i];
// ������ֵ�Դ����㣬���ʾ���ͱ�־���������־������ʣ������з���ո�
87 while(size-->0)
88 *str++ = ' ';
89 return str; // ����ת���õ�ָ���ַ���ĩ�˺��ָ�롣
90 }
91
// ���溯������ʽ��������ַ����С�
// Ϊ�������ں���ʹ�ø�ʽ���������Linus���ں�ʵ���˸�C��������
// ���в���fmt�Ǹ�ʽ�ַ�����args�Ǹ����仯��ֵ��buf������ַ�����������
// ��μ��������б�����йظ�ʽת���ַ��Ľ��ܡ�
92 int vsprintf(char *buf, const char *fmt, va_list args)
93 {
94 int len;
95 int i;
96 char * str; // ���ڴ��ת�������е��ַ�����
97 char *s;
98 int *ip;
99
100 int flags; /* flags to number() */
101 /* number()����ʹ�õı�־ */
102 int field_width; /* width of output field */
/* ����ֶο���*/
103 int precision; /* min. # of digits for integers; max
104 number of chars for from string */
/* min. �������ָ�����max. �ַ������ַ����� */
105 int qualifier; /* 'h', 'l', or 'L' for integer fields */
106 /* 'h', 'l',��'L'���������ֶ� */
// ���Ƚ��ַ�ָ��ָ��buf��Ȼ��ɨ���ʽ�ַ������Ը�����ʽת��ָʾ������Ӧ�Ĵ�����
107 for (str=buf ; *fmt ; ++fmt) {
// ��ʽת��ָʾ�ַ�������'%'��ʼ�������fmt��ʽ�ַ�����ɨ��'%'��Ѱ�Ҹ�ʽת���ַ����Ŀ�ʼ��
// ���Ǹ�ʽָʾ��һ���ַ��������δ���str��
108 if (*fmt != '%') {
109 *str++ = *fmt;
110 continue;
111 }
112
// ����ȡ�ø�ʽָʾ�ַ����еı�־������־��������flags�����С�
113 /* process flags */
114 flags = 0;
115 repeat:
116 ++fmt; /* this also skips first '%' */
117 switch (*fmt) {
118 case '-': flags |= LEFT; goto repeat; // ���������
119 case '+': flags |= PLUS; goto repeat; // �żӺš�
120 case ' ': flags |= SPACE; goto repeat; // �ſո�
121 case '#': flags |= SPECIAL; goto repeat; // ������ת����
122 case '': flags |= ZEROPAD; goto repeat; // Ҫ����(��'0')��
123 }
124
// ȡ��ǰ�����ֶο�����ֵ������field_width�����С����������������ֵ��ֱ��ȡ��Ϊ����ֵ��
// ��������������ַ�'*'����ʾ��һ������ָ�����ȡ���˵���va_argȡ����ֵ������ʱ����ֵ
// С��0����ø�����ʾ����б�־��'-'��־�����룩����˻����ڱ�־����������ñ�־����
// ���ֶο���ֵȡΪ�����ֵ��
125 /* get field width */
126 field_width = -1;
127 if (is_digit(*fmt))
128 field_width = skip_atoi(&fmt);
129 else if (*fmt == '*') {
130 /* it's the next argument */ // �����и�bug��Ӧ����++fmt;
131 field_width = va_arg(args, int);
132 if (field_width < 0) {
133 field_width = -field_width;
134 flags |= LEFT;
135 }
136 }
137
// ������δ��룬ȡ��ʽת�����ľ���������precision�����С�������ʼ�ı�־��'.'��
// �䴦���������������������ơ����������������ֵ��ֱ��ȡ��Ϊ����ֵ���������������
// �ַ�'*'����ʾ��һ������ָ�����ȡ���˵���va_argȡ����ֵ������ʱ����ֵС��0����
// �ֶξ���ֵȡΪ0��
138 /* get the precision */
139 precision = -1;
140 if (*fmt == '.') {
141 ++fmt;
142 if (is_digit(*fmt))
143 precision = skip_atoi(&fmt);
144 else if (*fmt == '*') {
145 /* it's the next argument */ // ͬ������ҲӦ����++fmt;
146 precision = va_arg(args, int);
147 }
148 if (precision < 0)
149 precision = 0;
150 }
151
// ������δ�������������η������������qualifer��������h,l,L�ĺ���μ��б����˵������
152 /* get the conversion qualifier */
153 qualifier = -1;
154 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
155 qualifier = *fmt;
156 ++fmt;
157 }
158
// �������ת��ָʾ����
159 switch (*fmt) {
// ���ת��ָʾ����'c'�����ʾ��Ӧ����Ӧ���ַ�����ʱ�����־������������룬����ֶ�ǰ��
// ����'������ֵ-1'���ո��ַ���Ȼ���ٷ�������ַ��������������0�����ʾΪ���룬����
// �����ַ���������'����ֵ-1'���ո��ַ���
160 case 'c':
161 if (!(flags & LEFT))
162 while (--field_width > 0)
163 *str++ = ' ';
164 *str++ = (unsigned char) va_arg(args, int);
165 while (--field_width > 0)
166 *str++ = ' ';
167 break;
168
// ���ת��ָʾ����'s'�����ʾ��Ӧ�������ַ���������ȡ�����ַ����ij��ȣ����䳬���˾�����ֵ��
// ����չ������=�ַ������ȡ���ʱ�����־������������룬����ֶ�ǰ����'����ֵ-�ַ�������'
// ���ո��ַ���Ȼ���ٷ�������ַ����������������0�����ʾΪ���룬���ڲ����ַ�������
// ����'����ֵ-�ַ�������'���ո��ַ���
169 case 's':
170 s = va_arg(args, char *);
171 len = strlen(s);
172 if (precision < 0)
173 precision = len;
174 else if (len > precision)
175 len = precision;
176
177 if (!(flags & LEFT))
178 while (len < field_width--)
179 *str++ = ' ';
180 for (i = 0; i < len; ++i)
181 *str++ = *s++;
182 while (len < field_width--)
183 *str++ = ' ';
184 break;
185
// �����ʽת������'o'����ʾ�轫��Ӧ�IJ���ת���ɰ˽��������ַ���������number()����������
186 case 'o':
187 str = number(str, va_arg(args, unsigned long), 8,
188 field_width, precision, flags);
189 break;
190
// �����ʽת������'p'����ʾ��Ӧ������һ��ָ�����͡���ʱ���ò���û�����ÿ�������Ĭ�Ͽ���
// Ϊ8��������Ҫ���㡣Ȼ�����number()�������д�����
191 case 'p':
192 if (field_width == -1) {
193 field_width = 8;
194 flags |= ZEROPAD;
195 }
196 str = number(str,
197 (unsigned long) va_arg(args, void *), 16,
198 field_width, precision, flags);
199 break;
200
// ����ʽת��ָʾ��'x'��'X'�����ʾ��Ӧ������Ҫ��ӡ��ʮ�������������'x'��ʾ��Сд��ĸ��ʾ��
201 case 'x':
202 flags |= SMALL;
203 case 'X':
204 str = number(str, va_arg(args, unsigned long), 16,
205 field_width, precision, flags);
206 break;
207
// �����ʽת���ַ���'d','i'��'u'�����ʾ��Ӧ������������'d', 'i'�������������������Ҫ����
// �����ű�־��'u'��������������
208 case 'd':
209 case 'i':
210 flags |= SIGN;
211 case 'u':
212 str = number(str, va_arg(args, unsigned long), 10,
213 field_width, precision, flags);
214 break;
215
// ����ʽת��ָʾ����'n'�����ʾҪ�ѵ�ĿǰΪֹת������ַ������浽��Ӧ����ָ��ָ����λ���С�
// ��������va_arg()ȡ�øò���ָ�룬Ȼ���Ѿ�ת���õ��ַ��������ָ����ָ��λ�á�
216 case 'n':
217 ip = va_arg(args, int *);
218 *ip = (str - buf);
219 break;
220
// ����ʽת��������'%'�����ʾ��ʽ�ַ����д���ֱ�ӽ�һ��'%'д��������С�
// �����ʽת������λ�ô������ַ�����Ҳֱ�ӽ����ַ�д��������У������ص�107�м�������
// ��ʽ�ַ����������ʾ�Ѿ���������ʽ�ַ����Ľ�β�������˳�ѭ����
221 default:
222 if (*fmt != '%')
223 *str++ = '%';
224 if (*fmt)
225 *str++ = *fmt;
226 else
227 --fmt;
228 break;
229 }
230 }
231 *str = '\0'; // �����ת���õ��ַ�����β������null��
232 return str-buf; // ����ת���õ��ַ�������ֵ��
233 }
234
1 /*
2 * linux/kernel/printk.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * When in kernel-mode, we cannot use printf, as fs is liable to
9 * point to 'interesting' things. Make a printf with fs-saving, and
10 * all is well.
11 */
/*
* �������ں�ģʽʱ�����Dz���ʹ��printf����Ϊ�Ĵ���fsָ������������Ȥ
* �ĵط����Լ�����һ��printf����ʹ��ǰ����fs��һ�оͽ���ˡ�
*/
// ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-������(va_list)��������
// va_start��va_arg��va_end������vsprintf��vprintf��vfprintf������
12 #include <stdarg.h>
13 #include <stddef.h> // ������ͷ�ļ���������NULL, offsetof(TYPE, MEMBER)��
14
15 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
16
17 static char buf[1024]; // ��ʾ����ʱ��������
18
// ����vsprintf()������linux/kernel/vsprintf.c��92�п�ʼ����
19 extern int vsprintf(char * buf, const char * fmt, va_list args);
20
// �ں�ʹ�õ���ʾ������
21 int printk(const char *fmt, ...)
22 {
23 va_list args; // va_listʵ������һ���ַ�ָ�����͡�
24 int i;
25
// ���в���������ʼ������Ȼ��ʹ�ø�ʽ��fmt�������б�args�����buf�С�����ֵi
// ��������ַ����ij��ȡ������в����������������������ÿ���̨��ʾ������������ʾ
// �ַ�����
26 va_start(args, fmt);
27 i=vsprintf(buf,fmt,args);
28 va_end(args);
29 console_print(buf); // chr_drv/console.c����995�п�ʼ��
30 return i;
31 }
32
1 /*
2 * linux/kernel/panic.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This function is used through-out the kernel (includeinh mm and fs)
9 * to indicate a major problem.
10 */
/*
* �ú����������ں���ʹ�ã������� ͷ�ļ�*.h, �ڴ��������mm���ļ�ϵͳfs�У���
* ����ָ����Ҫ�ij������⡣
*/
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct����ʼ����0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
13
14 void sys_sync(void); /* it's really int */ /* ʵ����������int (fs/buffer.c,44) */
15
// �ú���������ʾ�ں��г��ֵ��ش������Ϣ���������ļ�ϵͳͬ��������Ȼ�������ѭ��--������
// �����ǰ����������0�Ļ�����˵���ǽ���������������һ�û�������ļ�ϵͳͬ��������
// ������ǰ�Ĺؼ���volatile���ڸ��߱�����gcc�ú������᷵�ء���������gcc��������һЩ��
// ���룬����Ҫ����ʹ������ؼ��ֿ��Ա������ijЩ��δ��ʼ�������ģ��پ�����Ϣ��
// ��ͬ������gcc�ĺ�������˵����void panic(const char *s) __attribute__ ((noreturn));
16 volatile void panic(const char * s)
17 {
18 printk("Kernel panic: %s\n\r",s);
19 if (current == task[0])
20 printk("In swapper task - not syncing\n\r");
21 else
22 sys_sync();
23 for(;;);
24 }
25
1 #ifndef _BLK_H
2 #define _BLK_H
3
4 #define NR_BLK_DEV 7 // ���豸����������
5 /*
6 * NR_REQUEST is the number of entries in the request-queue.
7 * NOTE that writes may use only the low 2/3 of these: reads
8 * take precedence.
9 *
10 * 32 seems to be a reasonable number: enough to get some benefit
11 * from the elevator-mechanism, but not so much as to lock a lot of
12 * buffers when they are in the queue. 64 seems to be too many (easily
13 * long pauses in reading when heavy writing/syncing is going on)
14 */
/*
* ���涨���NR_REQUEST�������������������������
* ע�⣬д������ʹ����Щ���еͶ˵�2/3����������ȴ�����
*
* 32�������һ�����������֣������Ѿ��㹻�ӵ����㷨�л�úô���
* �����������ڶ����ж���סʱ�ֲ��Ե��Ǻܴ������64�Ϳ���ȥ̫
* ���ˣ���������д/ͬ����������ʱ����������ʱ�����ͣ����
*/
15 #define NR_REQUEST 32
16
17 /*
18 * Ok, this is an expanded form so that we can use the same
19 * request for paging requests when that is implemented. In
20 * paging, 'bh' is NULL, and 'waiting' is used to wait for
21 * read/write completion.
22 */
/*
* OK��������request�ṹ��һ����չ��ʽ�������ʵ���Ժ�����
* �Ϳ����ڷ�ҳ������ʹ��ͬ���� request �ṹ�� �ڷ�ҳ�����У�
* 'bh'��NULL����'waiting'�����ڵȴ���/д����ɡ�
*/
// �����������������Ľṹ����������ֶ�dev = -1�����ʾ�����и���û�б�ʹ�á�
// �ֶ�cmd��ȡ���� READ��0���� WRITE��1����������include/linux/fs.h�У���
// ���У��ں˲�û���õ�waitingָ�룬�����֮���ں�ʹ���˻����ĵȴ����С���Ϊ
// �ȴ�һ���������ȴ�����������ǶԵȵġ�
23 struct request {
24 int dev; /* -1 if no request */ // ��������豸�š�
25 int cmd; /* READ or WRITE */ // READ��WRITE���
26 int errors; //����ʱ�����Ĵ��������
27 unsigned long sector; // ��ʼ������(1��=2����)
28 unsigned long nr_sectors; // ��/�������
29 char * buffer; // ���ݻ�������
30 struct task_struct * waiting; // ����ȴ�������ɲ����ĵط������У���
31 struct buffer_head * bh; // ������ͷָ��(include/linux/fs.h,68)��
32 struct request * next; // ָ����һ�����
33 };
34
35 /*
36 * This is used in the elevator algorithm: Note that
37 * reads always go before writes. This is natural: reads
38 * are much more time-critical than writes.
39 */
/*
* ����Ķ������ڵ����㷨��ע�������������д����֮ǰ���С�
* ���Ǻ���Ȼ�ģ���������ʱ���Ҫ��Ҫ��д�����ϸ�öࡣ
*/
// ������в���s1��s2��ȡֵ�����涨�������ṹrequest��ָ�롣�ú궨�����ڸ�����������
// ָ����������ṹ�е���Ϣ������cmd��READ��WRITE�����豸��dev�Լ���������������sector��
// ���жϳ�����������ṹ��ǰ������˳�����˳���������ʿ��豸ʱ��������ִ��˳��
// �������ڳ���blk_drv/ll_rw_blk.c�к���add_request()�б����ã���96�У����ú겿��
// ��ʵ����I/O���ȹ��ܣ���ʵ���˶�������������ܣ���һ����������ϲ����ܣ���
40 #define IN_ORDER(s1,s2) \
41 ((s1)->cmd<(s2)->cmd || (s1)->cmd==(s2)->cmd && \
42 ((s1)->dev < (s2)->dev || ((s1)->dev == (s2)->dev && \
43 (s1)->sector < (s2)->sector)))
44
// ���豸�����ṹ��
45 struct blk_dev_struct {
46 void (*request_fn)(void); // ����������ָ�롣
47 struct request * current_request; // ��ǰ����������ṹ��
48 };
49
// ���豸�������飩��ÿ�ֿ��豸ռ��һ���7�
50 extern struct blk_dev_struct blk_dev[NR_BLK_DEV];
// ����������飬��32�
51 extern struct request request[NR_REQUEST];
// �ȴ�����������Ľ��̶���ͷָ�롣
52 extern struct task_struct * wait_for_request;
53
// �豸���ݿ�����ָ�����顣ÿ��ָ����ָ��ָ�����豸�ŵ��ܿ�������hd_sizes[]������
// ��������ÿһ���Ӧ���豸��ȷ����һ�����豸����ӵ�е����ݿ�������1���С = 1KB����
54 extern int * blk_size[NR_BLK_DEV];
55
// �ڿ��豸����������hd.c��������ͷ�ļ�ʱ�������ȶ��������������豸�����豸�š�
// ������������63����90�о���Ϊ�������ļ����������������ȷ�ĺ궨�塣
56 #ifdef MAJOR_NR // ���豸�š�
57
58 /*
59 * Add entries as needed. Currently the only block devices
60 * supported are hard-disks and floppies.
61 */
/*
* ��Ҫʱ������Ŀ��Ŀǰ���豸��֧��Ӳ�̺����̣����������̣���
*/
62
// ���������MAJOR_NR = 1��RAM�����豸�ţ������������·��ų����ͺꡣ
63 #if (MAJOR_NR == 1)
64 /* ram disk */
65 #define DEVICE_NAME "ramdisk" // �豸���ƣ����ڴ������̡�����
66 #define DEVICE_REQUEST do_rd_request // �豸�������������
67 #define DEVICE_NR(device) ((device) & 7) // �豸�ţ�0 �C 7����
68 #define DEVICE_ON(device) // �����豸�����������뿪���رգ���
69 #define DEVICE_OFF(device) // �ر��豸��
70
// �������������MAJOR_NR = 2���������豸�ţ������������·��ų����ͺꡣ
71 #elif (MAJOR_NR == 2)
72 /* floppy */
73 #define DEVICE_NAME "floppy" // �豸���ƣ�������������������
74 #define DEVICE_INTR do_floppy // �豸�жϴ���������
75 #define DEVICE_REQUEST do_fd_request // �豸�������������
76 #define DEVICE_NR(device) ((device) & 3) // �豸�ţ�0 �C 3����
77 #define DEVICE_ON(device) floppy_on(DEVICE_NR(device)) // �����豸�ꡣ
78 #define DEVICE_OFF(device) floppy_off(DEVICE_NR(device)) // �ر��豸�ꡣ
79
// �������������MAJOR_NR = 3��Ӳ�����豸�ţ������������·��ų����ͺꡣ
80 #elif (MAJOR_NR == 3)
81 /* harddisk */
82 #define DEVICE_NAME "harddisk" // �豸���ƣ���Ӳ�̡�����
83 #define DEVICE_INTR do_hd // �豸�жϴ���������
84 #define DEVICE_TIMEOUT hd_timeout // �豸��ʱֵ��
85 #define DEVICE_REQUEST do_hd_request // �豸�������������
86 #define DEVICE_NR(device) (MINOR(device)/5) // �豸�š�
87 #define DEVICE_ON(device) // �����豸��
88 #define DEVICE_OFF(device) // �ر��豸��
89
// �����ڱ���Ԥ��������ʾ������Ϣ����δ֪���豸����
90 #elif
91 /* unknown blk device */
92 #error "unknown blk device"
93
94 #endif
95
// Ϊ�˱��ڱ�̱�ʾ�����ﶨ���������꣺CURRENT��ָ��ס�豸�ŵĵ�ǰ����ṹ��ָ�룬
// CURRENT_DEV �ǵ�ǰ������CURRENT���豸�š�
96 #define CURRENT (blk_dev[MAJOR_NR].current_request)
97 #define CURRENT_DEV DEVICE_NR(CURRENT->dev)
98
// ����������豸�жϴ������ų��������������Ϊһ������ָ�룬��Ĭ��ΪNULL��
99 #ifdef DEVICE_INTR
100 void (*DEVICE_INTR)(void) = NULL;
101 #endif
// ����������豸��ʱ���ų�����������ֵ����0��������SET_INTR()�ꡣ����ֻ����ꡣ
102 #ifdef DEVICE_TIMEOUT
103 int DEVICE_TIMEOUT = 0;
104 #define SET_INTR(x) (DEVICE_INTR = (x),DEVICE_TIMEOUT = 200)
105 #else
106 #define SET_INTR(x) (DEVICE_INTR = (x))
107 #endif
// �����豸������ų���DEVICE_REGUEST��һ���������������صľ�̬����ָ�롣
108 static void (DEVICE_REQUEST)(void);
109
// ����ָ���Ļ���顣
// ���ָ�������bh��û�б�����������ʾ������Ϣ�����û��������������ѵȴ�
// �û����Ľ��̡���Ϊ��Ƕ�����������ǻ����ͷָ�롣
110 extern inline void unlock_buffer(struct buffer_head * bh)
111 {
112 if (!bh->b_lock)
113 printk(DEVICE_NAME ": free buffer being unlocked\n");
114 bh->b_lock=0;
115 wake_up(&bh->b_wait);
116 }
117
// ������������
// ����uptodate�Ǹ��±�־��
// ���ȹر�ָ�����豸��Ȼ����˴ζ�д�������Ƿ���Ч�������Ч����ݲ���ֵ���û���
// �����ݸ��±�־���������û������� ������±�־����ֵ��0����ʾ�˴�������IJ�����ʧ
// �ܣ������ʾ��ؿ��豸IO������Ϣ�� ����ѵȴ���������Ľ����Լ��ȴ���������
// ����ֵĽ��̣��ͷŲ�������������ɾ������������ѵ�ǰ������ָ��ָ����һ�����
118 extern inline void end_request(int uptodate)
119 {
120 DEVICE_OFF(CURRENT->dev); // �ر��豸��
121 if (CURRENT->bh) { // CURRENTΪ��ǰ����ṹ��ָ�롣
122 CURRENT->bh->b_uptodate = uptodate; // �ø��±�־��
123 unlock_buffer(CURRENT->bh); // ������������
124 }
125 if (!uptodate) { // �����±�־Ϊ0����ʾ������Ϣ��
126 printk(DEVICE_NAME " I/O error\n\r");
127 printk("dev %04x, block %d\n\r",CURRENT->dev,
128 CURRENT->bh->b_blocknr);
129 }
130 wake_up(&CURRENT->waiting); // ���ѵȴ���������Ľ��̡�
131 wake_up(&wait_for_request); // ���ѵȴ�����������Ľ��̡�
132 CURRENT->dev = -1; // �ͷŸ������
133 CURRENT = CURRENT->next; // ָ����һ�����
134 }
135
// ����������豸��ʱ���ų���DEVICE_TIMEOUT������CLEAR_DEVICE_TIMEOUT���ų���
// Ϊ��DEVICE_TIMEOUT = 0����������CLEAR_DEVICE_TIMEOUTΪ�ա�
136 #ifdef DEVICE_TIMEOUT
137 #define CLEAR_DEVICE_TIMEOUT DEVICE_TIMEOUT = 0;
138 #else
139 #define CLEAR_DEVICE_TIMEOUT
140 #endif
141
// ����������豸�жϷ��ų���DEVICE_INTR������CLEAR_DEVICE_INTR���ų���Ϊ
// ��DEVICE_INTR = 0������������Ϊ�ա�
142 #ifdef DEVICE_INTR
143 #define CLEAR_DEVICE_INTR DEVICE_INTR = 0;
144 #else
145 #define CLEAR_DEVICE_INTR
146 #endif
147
// �����ʼ��������ꡣ
// ���ڼ������豸��������ʼ����������ij�ʼ���������ƣ��������Ϊ���Ƕ�����һ��
// ͳһ�ij�ʼ���ꡣ�ú����ڶԵ�ǰ���������һЩ��Ч���жϡ������������£�
// ����豸��ǰ������Ϊ�գ�NULL������ʾ���豸Ŀǰ������Ҫ�������������������ɨβ
// �������˳���Ӧ���������������ǰ���������豸�����豸�Ų��������������������
// ���ţ�˵������������ҵ��ˣ������ں���ʾ������Ϣ��ͣ�������������������õĻ����
// û�б�������Ҳ˵���ں˳���������⣬������ʾ������Ϣ��ͣ����
148 #define INIT_REQUEST \
149 repeat: \
150 if (!CURRENT) {\ // �����ǰ������ָ��ΪNULL�ء�
151 CLEAR_DEVICE_INTR \
152 CLEAR_DEVICE_TIMEOUT \
153 return; \
154 } \
155 if (MAJOR(CURRENT->dev) != MAJOR_NR) \ // �����ǰ�豸���豸�Ų�����ͣ����
156 panic(DEVICE_NAME ": request list destroyed"); \
157 if (CURRENT->bh) { \
158 if (!CURRENT->bh->b_lock) \ // ���������Ļ�����û������ͣ����
159 panic(DEVICE_NAME ": block not locked"); \
160 }
161
162 #endif
163
164 #endif
165
1 /*
2 * linux/kernel/hd.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This is the low-level hd interrupt support. It traverses the
9 * request-list, using interrupts to jump between functions. As
10 * all the functions are called within interrupts, we may not
11 * sleep. Special care is recommended.
12 *
13 * modified by Drew Eckhardt to check nr of hd's from the CMOS.
14 */
/*
* �������ǵײ�Ӳ���жϸ���������Ҫ����ɨ����������У�ʹ���ж�
* �ں���֮����ת���������еĺ����������ж�����õģ�������Щ����
* ������˯�ߡ����ر�ע�⡣
*
* ��Drew Eckhardt�ģ�����CMOS��Ϣ���Ӳ������
*/
15
16 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE��ѡ�
17 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
18 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�
19 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
20 #include <linux/hdreg.h> // Ӳ�̲���ͷ�ļ�������Ӳ�̼Ĵ����˿ڡ�״̬�롢����������Ϣ��
21 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵȵĻ��ꡣ
22 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
23 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
24
// ����Ӳ�����豸�ŷ��ų����������������У����豸�ű����ڰ���blk.h�ļ�֮ǰ�����塣
// ��Ϊblk.h�ļ���Ҫ�õ�������ų���ֵ��ȷ��һЩ��������ط��ų����ͺꡣ
25 #define MAJOR_NR 3 // Ӳ�����豸����3��
26 #include "blk.h" // ���豸ͷ�ļ��������������ݽṹ�����豸���ݽṹ�ͺ����Ϣ��
27
// ��CMOS�����꺯����
// ��κ��ȡCMOS��Ӳ����Ϣ��outb_p��inb_p��include/asm/io.h�ж���Ķ˿���������ꡣ
// ��init/main.c�ж�ȡCMOSʱ����Ϣ�ĺ���ȫһ����
28 #define CMOS_READ(addr) ({ \
29 outb_p(0x80|addr,0x70); \ // 0x70��д�˿ںţ�0x80|addr��Ҫ����CMOS�ڴ��ַ��
30 inb_p(0x71); \ // 0x71�Ƕ��˿ںš�
31 })
32
33 /* Max read/write errors/sector */
/* ÿ������/д�������������������� */
34 #define MAX_ERRORS 7 // ��/дһ������ʱ������������������
35 #define MAX_HD 2 // ϵͳ֧�ֵ����Ӳ������
36
// ����������������
// ��λ����ʱ��Ӳ���жϴ��������е��õ�����У������(311��)��
37 static void recal_intr(void);
// ��дӲ��ʧ�ܴ������ú�����
// ����������������������ø�λ��־Ҫ��ִ�и�λӲ�̿����������������ԣ�242�У���
38 static void bad_rw_intr(void);
39
// ����У����־���������˸ñ�־�������л����recal_intr()�Խ���ͷ�ƶ���0���档
40 static int recalibrate = 0;
// ��λ��־����������д����ʱ�����øñ�־��������ظ�λ�������Ը�λӲ�̺Ϳ�������
41 static int reset = 0;
42
43 /*
44 * This struct defines the HD's and their types.
45 */
/* ����ṹ������Ӳ�̲��������� */
// Ӳ����Ϣ�ṹ��Harddisk information struct����
// ���ֶηֱ��Ǵ�ͷ����ÿ�ŵ�����������������дǰԤ��������š���ͷ��½������š�
// �����ֽڡ����ǵĺ�����μ������б����˵����
46 struct hd_i_struct {
47 int head,sect,cyl,wpcom,lzone,ctl;
48 };
// ����Ѿ���include/linux/config.h�����ļ��ж����˷��ų���HD_TYPE����ȡ���ж���
// �õIJ�����ΪӲ����Ϣ����hd_info[]�е����ݡ�������Ĭ�϶���Ϊ0ֵ����setup()����
// �л����½������á�
49 #ifdef HD_TYPE
50 struct hd_i_struct hd_info[] = { HD_TYPE }; // Ӳ����Ϣ���顣
51 #define NR_HD ((sizeof (hd_info))/(sizeof (struct hd_i_struct))) // ����Ӳ�̸�����
52 #else
53 struct hd_i_struct hd_info[] = { {0,0,0,0,0,0},{0,0,0,0,0,0} };
54 static int NR_HD = 0;
55 #endif
56
// ����Ӳ�̷����ṹ������ÿ��������Ӳ��0����ʼ�����������ʼ�����źͷ�������������
// ����5�ı������������hd[0]��hd[5]�ȣ���������Ӳ�̵IJ�����
57 static struct hd_struct {
58 long start_sect; // ������Ӳ���е���ʼ���������ԣ�������
59 long nr_sects; // ����������������
60 } hd[5*MAX_HD]={{0,0},};
61
// Ӳ��ÿ���������ݿ��������顣
62 static int hd_sizes[5*MAX_HD] = {0, };
63
// ���˿�Ƕ����ꡣ���˿�port������nr�֣�������buf�С�
64 #define port_read(port,buf,nr) \
65 __asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di")
66
// д�˿�Ƕ����ꡣд�˿�port����дnr�֣���buf��ȡ���ݡ�
67 #define port_write(port,buf,nr) \
68 __asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si")
69
70 extern void hd_interrupt(void); // Ӳ���жϹ��̣�sys_call.s��235�У���
71 extern void rd_load(void); // �����̴������غ�����ramdisk.c��71�У���
72
73 /* This may be used only once, enforced by 'static int callable' */
/* ����ú���ֻ�ڳ�ʼ��ʱ������һ�Ρ��þ�̬����callable��Ϊ�ɵ��ñ�־��*/
// ϵͳ���ú�����
// ��������BIOS���ɳ�ʼ������init/main.c��init�ӳ�������Ϊָ��Ӳ�̲������ṹ��ָ�롣
// ��Ӳ�̲������ṹ����2��Ӳ�̲����������ݣ���32�ֽڣ����Ǵ��ڴ�0x90080�����ƶ�����
// 0x90080����Ӳ�̲���������setup.s��������ROM BIOS����ȡ�á�Ӳ�̲�������Ϣ�μ�����
// �б����˵���� ��������Ҫ�����Ƕ�ȡ CMOS��Ӳ�̲�������Ϣ����������Ӳ�̷����ṹhd��
// �����Լ���RAM�����̺��ļ�ϵͳ��
74 int sys_setup(void * BIOS)
75 {
76 static int callable = 1; // ���Ʊ�����ֻ�ܱ�����1�εı�־��
77 int i,drive;
78 unsigned char cmos_disks;
79 struct partition *p;
80 struct buffer_head * bh;
81
// ��������callable��־��ʹ�ñ�����ֻ�ܱ�����1�Ρ�Ȼ������Ӳ����Ϣ����hd_info[]��
// ����� include/linux/config.h �ļ����Ѷ����˷��ų���HD_TYPE����ô hd_info[]����
// �Ѿ���ǰ���49�������ú��ˡ��������Ҫ��ȡboot/setup.s���������ڴ�0x90080��
// ��ʼ��Ӳ�̲�������setup.s�������ڴ�˴����������һ������Ӳ�̲�������
82 if (!callable)
83 return -1;
84 callable = 0;
85 #ifndef HD_TYPE // ���û�ж���HD_TYPE�����ȡ��
86 for (drive=0 ; drive<2 ; drive++) {
87 hd_info[drive].cyl = *(unsigned short *) BIOS; // ��������
88 hd_info[drive].head = *(unsigned char *) (2+BIOS); // ��ͷ����
89 hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); // дǰԤ��������š�
90 hd_info[drive].ctl = *(unsigned char *) (8+BIOS); // �����ֽڡ�
91 hd_info[drive].lzone = *(unsigned short *) (12+BIOS);// ��ͷ��½������š�
92 hd_info[drive].sect = *(unsigned char *) (14+BIOS); // ÿ�ŵ���������
93 BIOS += 16; // ÿ��Ӳ�̲�������16�ֽڣ�����BIOSָ����һ����
94 }
// setup.s������ȡBIOSӲ�̲�������Ϣʱ�����ϵͳ��ֻ��1��Ӳ�̣��ͻὫ��Ӧ��2��
// Ӳ�̵�16�ֽ�ȫ�����㡣�������ֻҪ�жϵ�2��Ӳ���������Ƿ�Ϊ0�Ϳ���֪���Ƿ���
// ��2��Ӳ���ˡ�
95 if (hd_info[1].cyl)
96 NR_HD=2; // Ӳ������Ϊ2��
97 else
98 NR_HD=1;
99 #endif
// �����Ӳ����Ϣ����hd_info[]�Ѿ����úã�����ȷ����ϵͳ���е�Ӳ����NR_HD������
// ��ʼ����Ӳ�̷����ṹ����hd[]�����������0����5 �ֱ��ʾ����Ӳ�̵������������
// ��1��4��6��9�ֱ��ʾ����Ӳ�̵�4�������IJ����� �����������ñ�ʾӲ��������Ϣ
// �������0��5����
100 for (i=0 ; i<NR_HD ; i++) {
101 hd[i*5].start_sect = 0; // Ӳ����ʼ�����š�
102 hd[i*5].nr_sects = hd_info[i].head*
103 hd_info[i].sect*hd_info[i].cyl; // Ӳ������������
104 }
105
106 /*
107 We querry CMOS about hard disks : it could be that
108 we have a SCSI/ESDI/etc controller that is BIOS
109 compatable with ST-506, and thus showing up in our
110 BIOS table, but not register compatable, and therefore
111 not present in CMOS.
112
113 Furthurmore, we will assume that our ST-506 drives
114 <if any> are the primary drives in the system, and
115 the ones reflected as drive 1 or 2.
116
117 The first drive is stored in the high nibble of CMOS
118 byte 0x12, the second in the low nibble. This will be
119 either a 4 bit drive type or 0xf indicating use byte 0x19
120 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
121
122 Needless to say, a non-zero value means we have
123 an AT controller hard disk for that drive.
124
125
126 */
/*
���Ƕ�CMOS�й�Ӳ�̵���Ϣ��Щ���ɣ����ܻ���������������
������һ��SCSI/ESDI/�ȵĿ�������������ST-506��ʽ��BIOS
����ݵģ��������������ǵ�BIOS�������У���ȴ�ֲ��ǼĴ�
�����ݵģ������Щ������CMOS���ֲ����ڡ�
���⣬���Ǽ���ST-506������������еĻ�����ϵͳ�еĻ�����
������Ҳ����������1��2���ֵ���������
��1�����������������CMOS�ֽ�0x12�ĸ߰��ֽ��У���2��
����ڵͰ��ֽ��С���4λ�ֽ���Ϣ���������������ͣ�Ҳ����
����0xf��0xf��ʾʹ��CMOS��0x19�ֽ���Ϊ������1��8λ
�����ֽڣ�ʹ��CMOS��0x1A�ֽ���Ϊ������2�������ֽڡ�
��֮��һ������ֵ��ζ��Ӳ����һ��AT����������Ӳ�̡�
*/
127
// �����������ԭ������������������Ӳ�̵����Dz���AT���������ݵġ��й�CMOS��Ϣ
// ��μ���4����4.2.3.1�ڡ������CMOSƫ�Ƶ�ַ0x12������Ӳ�������ֽڡ�����Ͱ�
// �ֽ�ֵ������ŵ�2��Ӳ������ֵ����Ϊ0�����ʾϵͳ����Ӳ�̣������ʾϵͳֻ��1
// ��Ӳ�̡����0x12��������ֵΪ0�����ʾϵͳ��û��AT����Ӳ�̡�
128 if ((cmos_disks = CMOS_READ(0x12)) & 0xf0)
129 if (cmos_disks & 0x0f)
130 NR_HD = 2;
131 else
132 NR_HD = 1;
133 else
134 NR_HD = 0;
// ��NR_HD = 0��������Ӳ�̶�����AT���������ݵģ�����Ӳ�����ݽṹȫ���㡣
// ��NR_HD = 1����2��Ӳ�̵IJ������㡣
135 for (i = NR_HD ; i < 2 ; i++) {
136 hd[i*5].start_sect = 0;
137 hd[i*5].nr_sects = 0;
138 }
// �ã�����Ϊֹ�����Ѿ�����ȷ����ϵͳ��������Ӳ�̸���NR_HD��������������ȡÿ��Ӳ��
// �ϵ�1�������еķ�������Ϣ���������÷����ṹ����hd[] ��Ӳ�̸���������Ϣ��������
// �ö��麯��bread()��Ӳ�̵�1�����ݿ飨fs/buffer.c����267�У�����1��������0x300��
// 0x305 ���ֱ�������Ӳ�̵��豸�ţ���2��������0���������ȡ�Ŀ�š����������ɹ���
// �����ݻᱻ����ڻ����bh���������С��������ͷָ��bhΪ0����˵��������ʧ�ܣ���
// ��ʾ������Ϣ��ͣ�����������Ǹ���Ӳ�̵�1��������������ֽ�Ӧ����0xAA55���ж���
// �������ݵ���Ч�ԣ��Ӷ�����֪��������λ��ƫ��0x1BE��ʼ���ķ������Ƿ���Ч������Ч
// ��Ӳ�̷�������Ϣ����Ӳ�̷����ṹ����hd[]�С�����ͷ�bh��������
139 for (drive=0 ; drive<NR_HD ; drive++) {
140 if (!(bh = bread(0x300 + drive*5,0))) { // 0x300��0x305���豸�š�
141 printk("Unable to read partition table of drive %d\n\r",
142 drive);
143 panic("");
144 }
145 if (bh->b_data[510] != 0x55 || (unsigned char)
146 bh->b_data[511] != 0xAA) { // �ж�Ӳ�̱�־0xAA55��
147 printk("Bad partition table on drive %d\n\r",drive);
148 panic("");
149 }
150 p = 0x1BE + (void *)bh->b_data; // ������λ�ڵ�1����0x1BE����
151 for (i=1;i<5;i++,p++) {
152 hd[i+5*drive].start_sect = p->start_sect;
153 hd[i+5*drive].nr_sects = p->nr_sects;
154 }
155 brelse(bh); // �ͷ�Ϊ���Ӳ�����ݿ������Ļ�������
156 }
// �����ٶ�ÿ�������е����ݿ���������ͳ�ƣ���������Ӳ�̷��������ݿ�����hd_sizes[]�С�
// Ȼ�����豸���ݿ�����ָ������ı��豸��ָ������顣
157 for (i=0 ; i<5*MAX_HD ; i++)
158 hd_sizes[i] = hd[i].nr_sects>>1 ;
159 blk_size[MAJOR_NR] = hd_sizes;
// ���������������Ӳ�̷����ṹ����hd[]���������ȷʵ��Ӳ�̴��ڲ����Ѷ��������
// ��������ʾ����������������Ϣ��Ȼ������ϵͳ�ڴ��������м����������а����ĸ���
// ��ϵͳӳ��blk_drv/ramdisk.c����71�У�������ϵͳ�����������̵�������ж�������
// ���Ƿ��и��ļ�ϵͳ��ӳ�����ݡ�����У���ʱ�������̳�Ϊ�����̣����Ѹ�ӳ��
// ���ز���ŵ��������У�Ȼ��Ѵ�ʱ�ĸ��ļ�ϵͳ�豸��ROOT_DEV�ij������̵��豸�š�
// �����ٶԽ����豸���г�ʼ�������װ���ļ�ϵͳ��
160 if (NR_HD)
161 printk("Partition table%s ok.\n\r",(NR_HD>1)?"s":"");
162 rd_load(); // blk_drv/ramdisk.c����71��
163 init_swapping(); // mm/swap.c����199��
164 mount_root(); // fs/super.c����241��
165 return (0);
166 }
167
//// �жϲ�ѭ���ȴ�Ӳ�̿�����������
// ��Ӳ�̿�����״̬�Ĵ����˿�HD_STATUS(0x1f7)��ѭ��������е���������������λ��λ6��
// �Ƿ���λ���ҿ�����æλ��λ7���Ƿ�λ�� �������ֵretriesΪ0�����ʾ�ȴ�����
// �����е�ʱ���Ѿ���ʱ����������������ֵ��Ϊ0��˵���ڵȴ���ѭ����ʱ�������ڿ�����
// �ص�����״̬��OK��
// ʵ���ϣ����ǽ�����״̬�Ĵ���æλ��λ7���Ƿ�Ϊ1���жϿ������Ƿ���æ״̬������
// ���Ƿ��������λ6�Ƿ�Ϊ1�����������״̬�ء�������ǿ��ѵ�172������д�ɣ�
// ��while (--retries && (inb_p(HD_STATUS)&0x80));�����⣬�������ڵ�PC���ٶȶ��ܿ죬
// ������ǿ��ѵȴ���ѭ�������ټӴ�һЩ������������10����
168 static int controller_ready(void)
169 {
170 int retries = 100000;
171
172 while (--retries && (inb_p(HD_STATUS)&0xc0)!=0x40);
173 return (retries); // ���صȴ�ѭ��������
174 }
175
//// ���Ӳ��ִ��������״̬����win ��ʾ����˹��Ӳ�̵���д��
// ��ȡ״̬�Ĵ����е�����ִ�н��״̬�� ����0��ʾ������1��ʾ���������ִ���������
// ����Ҫ�ٶ�����Ĵ���HD_ERROR��0x1f1����
176 static int win_result(void)
177 {
178 int i=inb_p(HD_STATUS); // ȡ״̬��Ϣ��
179
180 if ((i & (BUSY_STAT | READY_STAT | WRERR_STAT | SEEK_STAT | ERR_STAT))
181 == (READY_STAT | SEEK_STAT))
182 return(0); /* ok */
183 if (i&1) i=inb(HD_ERROR); // ��ERR_STAT��λ�����ȡ����Ĵ�����
184 return (1);
185 }
186
//// ��Ӳ�̿�������������顣
// ������drive - Ӳ�̺�(0-1)��nsect - ��д��������sect - ��ʼ������
// head - ��ͷ�ţ� cyl - ����ţ� cmd - �����루�������������б�����
// intr_addr() - Ӳ���жϴ��������н����õ�C��������ָ�롣
// �ú�����Ӳ�̿���������֮��������ȫ��ָ�����do_hdΪӲ���жϴ��������н����õ�
// C��������ָ�롣Ȼ���ٷ���Ӳ�̿����ֽں�7�ֽڵIJ�������顣
// �ú�����Ӳ�̿���������֮��������ȫ�ֺ���ָ�����do_hdָ��Ӳ���жϴ��������н���
// ���õ�C����������Ȼ���ٷ���Ӳ�̿����ֽں�7�ֽڵIJ�������顣Ӳ���жϴ�������Ĵ�
// ��λ��kernel/sys_call.s�����235�д���
// ��191�ж���1���Ĵ�������__res���ñ�������������1���Ĵ����У��Ա��ڿ��ٷ��ʡ�
// �����ָ���Ĵ�������eax���������ǿ��Ѹþ�д�ɡ�register char __res asm("ax");����
187 static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
188 unsigned int head,unsigned int cyl,unsigned int cmd,
189 void (*intr_addr)(void))
190 {
191 register int port asm("dx"); // ����ֲ��Ĵ�������������ָ���Ĵ���dx�С�
192
// ���ȶԲ���������Ч�Լ�顣����������Ŵ���1��ֻ����0��1�����ߴ�ͷ�Ŵ���15�����
// ��֧�֣�ͣ����������жϲ�ѭ���ȴ�����������������ȴ�һ��ʱ�����δ�������ʾ
// Ӳ�̿�����������Ҳͣ����
193 if (drive>1 || head>15)
194 panic("Trying to write bad sector");
195 if (!controller_ready())
196 panic("HD controller not ready");
// ������������Ӳ���жϷ���ʱ�����õ�C����ָ��do_hd���ú���ָ�붨����blk.h�ļ���
// ��56--109��֮�䣬���ر��������еĵ�83�к�100�У���Ȼ������Ӳ�̿��������Ͳ���
// ������֮ǰ���涨Ҫ�������������˿ڣ�0x3f6������һָ��Ӳ�̵Ŀ����ֽڣ��Խ�����
// Ӧ��Ӳ�̿��Ʒ�ʽ���ÿ����ֽڼ���Ӳ����Ϣ�ṹ�����е� ctl �ֶΡ�Ȼ����������˿�
// 0x1f1�C0x1f7����7�ֽڵIJ�������顣
197 SET_INTR(intr_addr); // do_hd = intr_addr���ж��б����á�
198 outb_p(hd_info[drive].ctl,HD_CMD); // ����ƼĴ�����������ֽڡ�
199 port=HD_DATA; // ��dxΪ���ݼĴ����˿�(0x1f0)��
200 outb_p(hd_info[drive].wpcom>>2,++port); // ������дԤ���������(���4)��
201 outb_p(nsect,++port); // ��������/���������
202 outb_p(sect,++port); // ��������ʼ������
203 outb_p(cyl,++port); // ����������ŵ�8λ��
204 outb_p(cyl>>8,++port); // ����������Ÿ�8λ��
205 outb_p(0xA0|(drive<<4)|head,++port); // ��������������+��ͷ�š�
206 outb(cmd,++port); // ���Ӳ�̿������
207 }
208
//// �ȴ�Ӳ�̾�����
// �ú���ѭ���ȴ���״̬������æ��־λ��λ�������о�����Ѱ��������־��λ�����ʾӲ��
// �������ɹ�����0��������һ��ʱ����Ϊæ����1��
209 static int drive_busy(void)
210 {
211 unsigned int i;
212 unsigned char c;
213
// ѭ����ȡ����������״̬�Ĵ���HD_STATUS���ȴ�������־λ��λ����æλ��λ��Ȼ����
// ����æλ������λ��Ѱ������λ�������о�����Ѱ��������־��λ�����ʾӲ�̾���������
// 0�������ʾ�ȴ���ʱ�����Ǿ�����ʾ��Ϣ��������1��
214 for (i = 0; i < 50000; i++) {
215 c = inb_p(HD_STATUS); // ȡ��������״̬�ֽڡ�
216 c &= (BUSY_STAT | READY_STAT | SEEK_STAT);
217 if (c == (READY_STAT | SEEK_STAT))
218 return 0;
219 }
220 printk("HD controller times out\n\r"); // �ȴ���ʱ����ʾ��Ϣ��������1��
221 return(1);
222 }
223
//// ��ϸ�λ������У����Ӳ�̿�������
// ��������ƼĴ����˿ڣ�0x3f6������������λ��4�������ֽڡ�Ȼ��ѭ���ղ����ȴ�һ��ʱ
// ���ÿ�����ִ�и�λ��������������ö˿ڷ��������Ŀ����ֽ�(����ֹ���ԡ��ض�)������
// ��Ӳ�̾��������ȴ�Ӳ�̾�����ʱ������ʾ������Ϣ��Ȼ���ȡ����Ĵ������ݣ����䲻��
// ��1����ʾ��������ʾӲ�̿�������λʧ����Ϣ��
224 static void reset_controller(void)
225 {
226 int i;
227
228 outb(4,HD_CMD); // ����ƼĴ����˿ڷ���λ�����ֽڡ�
229 for(i = 0; i < 1000; i++) nop(); // �ȴ�һ��ʱ�䡣
230 outb(hd_info[0].ctl & 0x0f ,HD_CMD); // �������������ֽ�(����ֹ���ԡ��ض�)��
231 if (drive_busy())
232 printk("HD-controller still busy\n\r");
233 if ((i = inb(HD_ERROR)) != 1)
234 printk("HD-controller reset failed: %02x\n\r",i);
235 }
236
//// Ӳ�̸�λ������
// ���ȸ�λ������У����Ӳ�̿�������Ȼ����Ӳ�̿���������������������������ڱ�
// ���������Ӳ���жϴ����������ֻ���ñ���������ʱ�ú��������ִ�и�����Ľ����
// ���Ƿ�Ҫ���г����������Ǽ���ִ���������������
237 static void reset_hd(void)
238 {
239 static int i;
240
// �����λ��־reset����λ�ģ����ڰѸ�λ��־�����ִ�и�λӲ�̿�����������Ȼ��
// ��Ե�i��Ӳ������������͡����������������������������ִ���˸�������ֻ�
// ����Ӳ���ж��źš���ʱ�������ᱻ�жϹ��̵��ö��ٴ�ִ�С�����reset�Ѿ���־��λ��
// ��˻�����ȥִ��246�п�ʼ����䣬�ж�����ִ���Ƿ������������Ƿ�������ͻ����
// bad_rw_intr() ������ͳ�Ƴ������������ݴ�ȷ���Ƿ�������reset��־�������������
// reset��־����ת��repeat����ִ�б�����������λ�����������������һ��Ӳ�̷���
// �����������������������������ͬ�����������ϵͳ��NR_HD��Ӳ�̶��Ѿ�����ִ��
// �˷��͵�������ٴ�do_hd_request()������ʼ����������д�����
241 repeat:
242 if (reset) {
243 reset = 0;
244 i = -1; // ��ʼ����ǰӲ�̺ţ���̬��������
245 reset_controller();
246 } else if (win_result()) {
247 bad_rw_intr();
248 if (reset)
249 goto repeat;
250 }
251 i++; // ������һ��Ӳ�̣���1����0����
252 if (i < NR_HD) {
253 hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1,
254 hd_info[i].cyl,WIN_SPECIFY,&reset_hd);
255 } else
256 do_hd_request(); // ִ�����������
257 }
258
//// ����Ӳ���жϵ��ú�����
// ��������Ӳ���ж�ʱ��Ӳ���жϴ��������е��õ�Ĭ��C�����������ڱ����ú���ָ��Ϊ
// NULLʱ���øú������μ���kernel/sys_call.s����256�У����ú�������ʾ������Ϣ��
// ���ø�λ��־reset��Ȼ����������������go_hd_request()��������ִ�и�λ����
// ������
259 void unexpected_hd_interrupt(void)
260 {
261 printk("Unexpected HD interrupt\n\r");
262 reset = 1;
263 do_hd_request();
264 }
265
//// ��дӲ��ʧ�ܴ������ú�����
// ���������ʱ�ij����������ڻ����7��ʱ���������ǰ��������ѵȴ�������Ľ��̣�
// ���Ҷ�Ӧ���������±�־��λ����ʾ����û�и��¡������дһ����ʱ�ij��������Ѿ�����
// 3�Σ���Ҫ��ִ�и�λӲ�̿��������������ø�λ��־����
266 static void bad_rw_intr(void)
267 {
268 if (++CURRENT->errors >= MAX_ERRORS)
269 end_request(0);
270 if (CURRENT->errors > MAX_ERRORS/2)
271 reset = 1;
272 }
273
//// �������жϵ��ú�����
// �ú�������Ӳ�̶��������ʱ������Ӳ���жϹ����б����á�
// �ڶ�����ִ�к�����Ӳ���ж��źţ���ִ��Ӳ���жϴ�������ʱ��Ӳ���жϴ�������
// �е��õ�C����ָ��do_hd�Ѿ�ָ��read_intr()����˻���һ�ζ�����������ɣ��������
// ��ͻ�ִ�иú�����
274 static void read_intr(void)
275 {
// �ú��������жϴ˴ζ���������Ƿ����������������������������æ״̬����������
// ִ�д�������Ӳ�̲���ʧ�����⣬�����ٴ�����Ӳ������λ������ִ�����������
// Ȼ�ء�ÿ�ζ�������������Ե�ǰ�����������������ۼƣ����������������������
// ����������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ�б������������������������
// �����ڵ������������������MAX_ERRORS��7�Σ������������������Ĵ�����ȥ������
// ������һ�������
276 if (win_result()) { // ��������æ����д��������ִ�д���
277 bad_rw_intr(); // ����ж�дӲ��ʧ�ܴ�����
278 do_hd_request(); // �ٴ�����Ӳ������Ӧ(��λ)������
279 return;
280 }
// ���������û�г�����������ݼĴ����˿ڰ�1�����������ݶ���������Ļ������У�����
// �ݼ������������ȡ��������ֵ�����ݼ����� 0����ʾ��������������ûȡ�꣬����
// �ٴ����жϵ���C����ָ��do_hdΪread_intr()��ֱ�ӷ��أ��ȴ�Ӳ���ڶ�����1������
// ���ݺ��жϲ��ٴε��ñ�������ע�⣺281������е�256��ָ�ڴ��֣���512�ֽڡ�
// ע��1��262���ٴ���do_hdָ��ָ��read_intr()����ΪӲ���жϴ�������ÿ�ε���do_hd
// ʱ���Ὣ�ú���ָ���ÿա��μ�sys_call.s�����251��253�С�
281 port_read(HD_DATA,CURRENT->buffer,256); // �����ݵ�����ṹ��������
282 CURRENT->errors = 0; // �����������
283 CURRENT->buffer += 512; // ����������ָ�룬ָ���µĿ�����
284 CURRENT->sector++; // ��ʼ�����ż�1��
285 if (--CURRENT->nr_sectors) { // ��������������������û���꣬����
286 SET_INTR(&read_intr); // ��Ӳ�̵���C����ָ��Ϊread_intr()��
287 return;
288 }
// ִ�е��ˣ�˵�������������ȫ�����������Ѿ����꣬�����end_request()����ȥ������
// ����������ˡ� ����ٴε��� do_hd_request()��ȥ��������Ӳ�������ִ������Ӳ��
// ���������
289 end_request(1); // �����Ѹ��±�־��λ��1����
290 do_hd_request();
291 }
292
//// д�����жϵ��ú�����
// �ú�������Ӳ��д�������ʱ������Ӳ���жϹ����б����á�����������read_intr()���ơ�
// ��д����ִ�к�����Ӳ���ж��źţ���ִ��Ӳ���жϴ�������ʱ��Ӳ���жϴ�������
// �е��õ�C����ָ��do_hd�Ѿ�ָ��write_intr()����˻���һ��д����������ɣ��������
// ��ͻ�ִ�иú�����
293 static void write_intr(void)
294 {
// �ú��������жϴ˴�д��������Ƿ����������������������������æ״̬����������
// ִ�д�������Ӳ�̲���ʧ�����⣬�����ٴ�����Ӳ������λ������ִ�����������
// Ȼ�ء��� bad_rw_intr() �����У�ÿ�β�����������Ե�ǰ�����������������ۼƣ�
// �������������������������������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ�б�����
// ������������������Ѿ����ڵ������������������MAX_ERRORS��7�Σ������������
// ������Ĵ�����ȥ������������һ�������do_hd_request()�л���ݵ�ʱ����ı�־
// ״̬���б��Ƿ���Ҫ��ִ�и�λ������У���Ȳ�����Ȼ���ټ���������һ�������
295 if (win_result()) { // ���Ӳ�̿��������ش�����Ϣ��
296 bad_rw_intr(); // �����Ƚ���Ӳ�̶�дʧ�ܴ�����
297 do_hd_request(); // �ٴ�����Ӳ������Ӧ(��λ)������
298 return;
299 }
// ��ʱ˵������дһ���������ɹ�����˽���д��������1�����䲻Ϊ0����˵����������
// Ҫд�����ǰѵ�ǰ������ʼ������ +1�����������������ݻ�����ָ��ָ����һ����д��
// ���ݡ�Ȼ��������Ӳ���жϴ��������е��õ�C����ָ��do_hd��ָ��������������
// ���������ݶ˿�д��512�ֽ����ݣ�Ȼ��������ȥ�ȴ�����������Щ����д��Ӳ�̺��
// �����жϡ�
300 if (--CURRENT->nr_sectors) { // ����������Ҫд����
301 CURRENT->sector++; // ��ǰ������ʼ������+1��
302 CURRENT->buffer += 512; // ����������ָ�룬
303 SET_INTR(&write_intr); // do_hd�ú���ָ��Ϊwrite_intr()��
304 port_write(HD_DATA,CURRENT->buffer,256); // �����ݶ˿�д256�֡�
305 return;
306 }
// �������������ȫ�����������Ѿ�д�꣬�����end_request()����ȥ����������������ˡ�
// ����ٴε��� do_hd_request()��ȥ��������Ӳ�������ִ������Ӳ�����������
307 end_request(1); // ��������������ˣ������ø��±�־����
308 do_hd_request(); // ִ������Ӳ�����������
309 }
310
//// Ӳ������У������λ���жϵ��ú�����
// �ú�������Ӳ��ִ������У��������������Ӳ���ж��б����á�
// ���Ӳ�̿��������ش�����Ϣ���������Ƚ���Ӳ�̶�дʧ�ܴ�����Ȼ������Ӳ������Ӧ
// ����λ�������� �� bad_rw_intr() �����У�ÿ�β�����������Ե�ǰ����������������
// �ۼƣ��������������������������������һ�룬�����ִ��Ӳ�̸�λ������Ȼ����ִ��
// ������������������������Ѿ����ڵ������������������MAX_ERRORS��7�Σ������
// ������������Ĵ�����ȥ������������һ�������do_hd_request() �л���ݵ�ʱ����
// �ı�־״̬���б��Ƿ���Ҫ��ִ�и�λ������У���Ȳ�����Ȼ���ټ���������һ�����
311 static void recal_intr(void)
312 {
313 if (win_result()) // �����س����������bad_rw_intr()��
314 bad_rw_intr();
315 do_hd_request();
316 }
317
// Ӳ�̲�����ʱ������
// ����������do_timer()�У�kernel/sched.c����340�У������á�����Ӳ�̿�����������
// һ����������ھ�����hd_timeout��ϵͳ�δ���������û�з���һ��Ӳ���ж��źţ�
// ��˵������������Ӳ�̣�������ʱ����ʱdo_timer()�ͻ���ñ��������ø�λ��־reset
// ������do_hd_request()ִ�и�λ����������Ԥ��ʱ���ڣ�200�δ�Ӳ�̿�����������Ӳ
// ���жϲ���ʼִ��Ӳ���жϴ���������ôht_timeoutֵ�ͻ����жϴ��������б���0��
// ��ʱdo_timer()�ͻ�������������
318 void hd_times_out(void)
319 {
// �����ǰ��û��������Ҫ�������豸������ָ��ΪNULL��������ʱ���ԣ�ֱ�ӷ��ء���
// ������ʾ������Ϣ��Ȼ���жϵ�ǰ������ִ�й����з����ij��������Ƿ��Ѿ������趨ֵ
// MAX_ERRORS��7�������������ʧ����ʽ��������������Ĵ��������������ݸ��±�־����
// Ȼ����жϹ����е��õ�C����ָ��do_hd�ÿգ������ø�λ��־reset���̶���������
// ��������do_hd_request()��ȥִ�и�λ������
320 if (!CURRENT)
321 return;
322 printk("HD timeout");
323 if (++CURRENT->errors >= MAX_ERRORS)
324 end_request(0);
325 SET_INTR(NULL); // ��do_hd = NULL,time_out=200��
326 reset = 1; // ���ø�λ��־��
327 do_hd_request();
328 }
329
//// ִ��Ӳ�̶�д���������
// �ú��������豸��ǰ�������е��豸�ź���ʼ��������Ϣ���ȼ���õ���ӦӲ���ϵ�����š�
// ��ǰ�ŵ��������š���ͷ�����ݣ�Ȼ���ٸ����������е����READ/WRITE����Ӳ�̷�����Ӧ
// ��/д��� ����������λ��־��Ӳ������У����־�ѱ���λ����ô���Ȼ�ȥִ�и�λ������
// ��������
// ���������ʱ�ǿ��豸�ĵ�1����ԭ���豸���У�������豸��ǰ������ָ���ֱ��ָ�����
// ����μ�ll_rw_blk.c��28�У����������̵��ñ�����ִ�ж�д������������һ����д����
// ��ɶ�������Ӳ���жϹ����У���������������Ҫ��������Ҳ����Ӳ���жϹ����е��ñ�������
// �μ�kernel/sys_call.s��235�С�
330 void do_hd_request(void)
331 {
332 int i,r;
333 unsigned int block,dev;
334 unsigned int sec,head,cyl;
335 unsigned int nsect;
336
// �������ȼ��������ĺϷ��ԡ��������������û�����������˳����μ�blk.h��127�У���
// Ȼ��ȡ�豸���е����豸�ţ����б����Ӳ���豸�ŵ�˵�����Լ��豸��ǰ�������е���ʼ
// �����š����豸�ż���ӦӲ���ϸ�������������豸�Ų����ڻ�����ʼ�������ڸ� ������
// ����-2������������������ת�����repeat����������INIT_REQUEST��ʼ��������Ϊ
// һ��Ҫ���дһ�����ݣ�2����������1024�ֽڣ�����������������Ų��ܴ��ڷ��������
// �����ڶ��������š�Ȼ��ͨ���������豸�Ŷ�Ӧ��������ʼ�����ţ��Ͱ���Ҫ��д�Ŀ��Ӧ
// ������Ӳ�̵ľ���������block�ϡ������豸�ű�5�������ɵõ���Ӧ��Ӳ�̺š�
337 INIT_REQUEST;
338 dev = MINOR(CURRENT->dev);
339 block = CURRENT->sector; // �������ʼ������
340 if (dev >= 5*NR_HD || block+2 > hd[dev].nr_sects) {
341 end_request(0);
342 goto repeat; // �ñ����blk.h����档
343 }
344 block += hd[dev].start_sect;
345 dev /= 5; // ��ʱdev����Ӳ�̺ţ�Ӳ��0����Ӳ��1����
// Ȼ�������õľ���������block��Ӳ�̺�dev�����ǾͿ��Լ������ӦӲ���еĴŵ�����
// ���ţ�sec������������ţ�cyl�� �ʹ�ͷ�ţ�head���� ����Ƕ��Ļ����뼴��������Ӳ
// ����Ϣ�ṹ�е�ÿ�ŵ���������Ӳ�̴�ͷ����������Щ���ݡ����㷽��Ϊ��
// 310--311�д����ʼʱeax��������block��edx����0��divlָ���edx:eax��ɵ�����
// �ų���ÿ�ŵ���������hd_info[dev].sect��������������ֵ��eax�У�������edx�С���
// ��eax���ǵ�ָ��λ�õĶ�Ӧ�ܴŵ��������д�ͷ�棩��edx���ǵ�ǰ�ŵ��ϵ������š�
// 312--313�д����ʼʱeax�Ǽ�����Ķ�Ӧ�ܴŵ�����edx����0��divlָ���edx:eax
// �Ķ�Ӧ�ܴŵ�������Ӳ���ܴ�ͷ����hd_info[dev].head������eax�еõ�������ֵ������
// �ţ�cyl����edx�еõ����������Ƕ�Ӧ�õ�ǰ��ͷ�ţ�head����
346 __asm__("divl %4":"=a" (block),"=d" (sec):"0" (block),"1" (0),
347 "r" (hd_info[dev].sect));
348 __asm__("divl %4":"=a" (cyl),"=d" (head):"0" (block),"1" (0),
349 "r" (hd_info[dev].head));
350 sec++; // �Լ������õ�ǰ�ŵ������Ž��е�����
351 nsect = CURRENT->nr_sectors; // ����/���������
// ��ʱ���ǵõ�������д��Ӳ����ʼ����block����Ӧ��Ӳ��������ţ�cyl�����ڵ�ǰ�ŵ�
// �ϵ������ţ�sec������ͷ�ţ�head���Լ�����д������������nsect���� �������ǿ��Ը�
// ����Щ��Ϣ��Ӳ�̿���������I/O������Ϣ�ˡ� ���ڷ���֮ǰ���ǻ���Ҫ�ȿ����Ƿ��и�
// λ������״̬������У��Ӳ�̵ı�־��ͨ���ڸ�λ����֮����Ҫ����У��Ӳ�̴�ͷλ�á�
// ����Щ��־�ѱ���λ����˵��ǰ���Ӳ�̲������ܳ�����һЩ���⣬����������ϵͳ��һ
// ��Ӳ�̶�д����������� �������Ǿ���Ҫ���¸�λӲ�̻������������У��Ӳ�̡�
// �����ʱ��λ��־reset����λ�ģ�����Ҫִ�и�λ��������λӲ�̺Ϳ�����������Ӳ��
// ��Ҫ����У����־�����ء�reset_hd()��������Ӳ�̿���������λ������У�������
// Ȼ����Ӳ�̿��������������������������
352 if (reset) {
353 recalibrate = 1; // ��������У����־��
354 reset_hd();
355 return;
356 }
// �����ʱ����У����־��recalibrate������λ�ģ������ȸ�λ�ñ�־��Ȼ����Ӳ�̿���
// ����������У������������ִ��Ѱ���������ô����κεط��Ĵ�ͷ�ƶ���0���档
357 if (recalibrate) {
358 recalibrate = 0;
359 hd_out(dev,hd_info[CURRENT_DEV].sect,0,0,0,
360 WIN_RESTORE,&recal_intr);
361 return;
362 }
// �������������־��û����λ����ô���ǾͿ��Կ�ʼ��Ӳ�̿������������������ݶ�/д
// ���������ˡ������ǰ������д��������������д���ѭ����ȡ״̬�Ĵ�����Ϣ����
// ����������־DRQ_STAT�Ƿ���λ��DRQ_STAT��Ӳ��״̬�Ĵ������������λ����ʾ��
// �����Ѿ����������������ݶ˿�֮�䴫��һ���ֻ�һ���ֽڵ����ݡ��ⷽ�����Ϣ�ɲ�
// ������ǰ���Ӳ�̲�����/дʱ��ͼ������������DRQ��λ���˳�ѭ���� ���ȵ�ѭ����
// ��Ҳû����λ�����ʾ���͵�Ҫ��дӲ������ʧ�ܣ�������תȥ�������ֵ���������ִ
// ����һ��Ӳ�����������ǾͿ�����Ӳ�̿��������ݼĴ����˿�HD_DATAд��1������
// �����ݡ�
363 if (CURRENT->cmd == WRITE) {
364 hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
365 for(i=0 ; i<10000 && !(r=inb_p(HD_STATUS)&DRQ_STAT) ; i++)
366 /* nothing */ ;
367 if (!r) {
368 bad_rw_intr();
369 goto repeat; // �ñ����blk.h�ļ�����档
370 }
371 port_write(HD_DATA,CURRENT->buffer,256);
// �����ǰ�����Ƕ�Ӳ�����ݣ�����Ӳ�̿��������Ͷ����������������Ч��ͣ����
372 } else if (CURRENT->cmd == READ) {
373 hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
374 } else
375 panic("unknown hd-command");
376 }
377
// Ӳ��ϵͳ��ʼ����
// ����Ӳ���ж���������������Ӳ�̿����������ж������źš�
// �ú�������Ӳ���豸�������������ָ��Ϊdo_hd_request()��Ȼ������Ӳ���ж�������
// ����hd_interrupt��kernel/sys_call.s����235�У������жϴ������̵�ַ�� Ӳ���жϺ�
// Ϊint 0x2E��46������Ӧ8259AоƬ���ж������ź�IRQ13�����Ÿ�λ��������8259A int2
// ������λ��������Ƭ�����ж������źš��ٸ�λӲ�̵��ж���������λ���ڴ�Ƭ�ϣ�������
// Ӳ�̿����������ж������źš��ж���������IDT���ж������������ú�set_intr_gate()
// ��include/asm/system.h��ʵ�֡�
378 void hd_init(void)
379 {
380 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; // do_hd_request()��
381 set_intr_gate(0x2E,&hd_interrupt); // �����ж����д�������ָ�롣
382 outb_p(inb_p(0x21)&0xfb,0x21); // ���������8259A int2�������
383 outb(inb_p(0xA1)&0xbf,0xA1); // ��λӲ���ж���������λ���ڴ�Ƭ�ϣ���
384 }
385
1 /*
2 * linux/kernel/blk_dev/ll_rw.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This handles all read/write requests to block devices
9 */
10 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
13 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
14
15 #include "blk.h" // ���豸ͷ�ļ��������������ݽṹ�����豸���ݽṹ�ͺ����Ϣ��
16
17 /*
18 * The request-struct contains all necessary data
19 * to load a nr of sectors into memory
20 */
/*
* ����ṹ�к��м���nr���������ݵ��ڴ���ȥ�����б������Ϣ��
*/
// �����������������NR_REQUEST = 32�������
21 struct request request[NR_REQUEST];
22
23 /*
24 * used to wait on when there are no free requests
25 */
/*
* ����������������û�п�����ʱ���̵���ʱ�ȴ�����
*/
26 struct task_struct * wait_for_request = NULL;
27
28 /* blk_dev_struct is:
29 * do_request-address
30 * next-request
31 */
/* blk_dev_struct���豸�ṹ�ǣ����μ��ļ�kernel/blk_drv/blk.h����45�У�
* do_request-address // ��Ӧ���豸�ŵ�����������ָ�롣
* current-request // ���豸����һ������
*/
// ���豸���顣������ʹ�����豸����Ϊ������ʵ�����ݽ��ڸ����豸���������ʼ��ʱ���롣
// ���磬Ӳ�����������ʼ��ʱ��hd.c��343�У�����һ����伴��������blk_dev[3]�����ݡ�
32 struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
33 { NULL, NULL }, /* no_dev */ // 0 - ���豸��
34 { NULL, NULL }, /* dev mem */ // 1 - �ڴ档
35 { NULL, NULL }, /* dev fd */ // 2 - �����豸��
36 { NULL, NULL }, /* dev hd */ // 3 - Ӳ���豸��
37 { NULL, NULL }, /* dev ttyx */ // 4 - ttyx�豸��
38 { NULL, NULL }, /* dev tty */ // 5 - tty�豸��
39 { NULL, NULL } /* dev lp */ // 6 - lp��ӡ���豸��
40 };
41
42 /*
43 * blk_size contains the size of all block-devices:
44 *
45 * blk_size[MAJOR][MINOR]
46 *
47 * if (!blk_size[MAJOR]) then no minor size checking is done.
48 */
/*
* blk_size���麬�����п��豸�Ĵ�С������������
* blk_size[MAJOR][MINOR]
* ��� (!blk_size[MAJOR])���ؼ�����豸�Ŀ�������
*/
// �豸���ݿ�����ָ�����顣ÿ��ָ����ָ��ָ�����豸�ŵ��ܿ������顣���ܿ�������ÿһ
// ���Ӧ���豸��ȷ����һ�����豸����ӵ�е����ݿ�������1���С = 1KB����
49 int * blk_size[NR_BLK_DEV] = { NULL, NULL, };
50
// ����ָ������顣
// ���ָ���Ļ�����Ѿ�������������������ʹ�Լ�˯�ߣ������жϵصȴ�����ֱ����ִ�н�
// ��������������ȷ�ػ��ѡ�
51 static inline void lock_buffer(struct buffer_head * bh)
52 {
53 cli(); // ���ж����ɡ�
54 while (bh->b_lock) // ����������ѱ�������˯�ߣ�ֱ��������������
55 sleep_on(&bh->b_wait);
56 bh->b_lock=1; // ���������û�������
57 sti(); // ���жϡ�
58 }
59
// �ͷţ������������Ļ�������
// �ú�����blk.h�ļ��е�ͬ��������ȫһ����
60 static inline void unlock_buffer(struct buffer_head * bh)
61 {
62 if (!bh->b_lock) // ����û�����û�б����������ӡ������Ϣ��
63 printk("ll_rw_block.c: buffer not locked\n\r");
64 bh->b_lock = 0; // ��������־��
65 wake_up(&bh->b_wait); // ���ѵȴ��û�����������
66 }
67
68 /*
69 * add-request adds a request to the linked list.
70 * It disables interrupts so that it can muck with the
71 * request-lists in peace.
72 *
73 * Note that swapping requests always go before other requests,
74 * and are done in the order they appear.
75 */
/*
* add-request()�������м���һ�����������ر��жϣ�
* �������ܰ�ȫ�ش������������ˡ�
*
* ע�⣬����������������������֮ǰ���������������dz�
* �ֵ�˳����ɡ�
*/
//// ��������������
// ����dev��ָ�����豸�ṹָ�룬�ýṹ���д����������ָ��͵�ǰ����������ָ�룻
// req�������ú����ݵ�������ṹָ�롣
// ���������Ѿ����úõ�������req���ӵ�ָ���豸�������������С�������豸�ĵ�ǰ����
// ������ָ��Ϊ�գ����������reqΪ��ǰ��������̵����豸�����������������Ͱ�
// req��������뵽�������������С�
76 static void add_request(struct blk_dev_struct * dev, struct request * req)
77 {
78 struct request * tmp;
79
// �����ٽ�һ���Բ����ṩ���������ָ��ͱ�־����ʼ���á��ÿ��������е���һ������ָ
// �룬���жϲ������������ػ��������־��
80 req->next = NULL;
81 cli(); // ���жϡ�
82 if (req->bh)
83 req->bh->b_dirt = 0; // �建�������ࡱ��־��
// Ȼ��鿴ָ���豸�Ƿ��е�ǰ��������鿴�豸�Ƿ���æ�����ָ���豸dev��ǰ������
// ��current_request���Ӷ�Ϊ�գ����ʾĿǰ���豸û������������ǵ�1�������Ҳ��
// Ψһ��һ������˿ɽ����豸��ǰ����ָ��ֱ��ָ��������������ִ����Ӧ�豸������
// ������
84 if (!(tmp = dev->current_request)) {
85 dev->current_request = req;
86 sti(); // ���жϡ�
87 (dev->request_fn)(); // ִ��������������Ӳ����do_hd_request()��
88 return;
89 }
// ���Ŀǰ���豸�Ѿ��е�ǰ�������ڴ��������������õ����㷨������Ѳ���λ�ã�Ȼ��
// ��ǰ��������뵽���������С������������У�����жϳ�������������Ļ����ͷָ��գ�
// ��û�л���飬��ô����Ҫ��һ������Ѿ��п��õĻ���顣�������ǰ����λ�ã�tmp
// ֮���Ŀ�������ͷָ�벻�գ���ѡ�����λ�á������˳�ѭ���������������˴���
// ����жϲ��˳������������㷨���������ô��̴�ͷ���ƶ�������С���Ӷ����ƣ����٣�
// Ӳ�̷���ʱ�䡣
// ����forѭ����if������ڰ�req��ָ��������������У������������е����������Ƚϣ�
// �ҳ�req����ö��е���ȷλ��˳��Ȼ���ж�ѭ��������req���뵽�ö�����ȷλ�ô���
90 for ( ; tmp->next ; tmp=tmp->next) {
91 if (!req->bh)
92 if (tmp->next->bh)
93 break;
94 else
95 continue;
96 if ((IN_ORDER(tmp,req) ||
97 !IN_ORDER(tmp,tmp->next)) &&
98 IN_ORDER(req,tmp->next))
99 break;
100 }
101 req->next=tmp->next;
102 tmp->next=req;
103 sti();
104 }
105
//// ����������������������
// ����major�����豸�ţ�rw��ָ�����bh�Ǵ�����ݵĻ�����ͷָ�롣
106 static void make_request(int major,int rw, struct buffer_head * bh)
107 {
108 struct request * req;
109 int rw_ahead;
110
111 /* WRITEA/READA is special case - it is not really needed, so if the */
112 /* buffer is locked, we just forget about it, else it's a normal read */
/* WRITEA/READA��һ��������� - ���Dz��DZ�Ҫ����������������Ѿ�������*/
/* ���ǾͲ��ù���������Ļ���ֻ��һ��һ��Ķ������� */
// ����'READ'��'WRITE'�����'A'�ַ�����Ӣ�ĵ���Ahead����ʾ��ǰԤ��/д���ݿ����˼��
// �ú������ȶ�����READA/WRITEA���������һЩ���������������������ָ���Ļ�����
// ����ʹ�ö��ѱ�����ʱ���ͷ���Ԥ��/д���������Ϊ��ͨ��READ/WRITE������в�����
// ���⣬�����������������Ȳ��� READҲ���� WRITE�����ʾ�ں˳����д�����ʾ������
// Ϣ��ͣ����ע�⣬��������֮ǰ������Ϊ�����Ƿ���Ԥ��/д���������˱�־rw_ahead��
113 if (rw_ahead = (rw == READA || rw == WRITEA)) {
114 if (bh->b_lock)
115 return;
116 if (rw == READA)
117 rw = READ;
118 else
119 rw = WRITE;
120 }
121 if (rw!=READ && rw!=WRITE)
122 panic("Bad block dev command, must be R/W/RA/WA");
123 lock_buffer(bh);
124 if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate)) {
125 unlock_buffer(bh);
126 return;
127 }
128 repeat:
129 /* we don't allow the write-requests to fill up the queue completely:
130 * we want some room for reads: they take precedence. The last third
131 * of the requests are only for reads.
132 */
/* ���Dz����ö�����ȫ����д�����������ҪΪ��������һЩ�ռ䣺������
* �����ȵġ�������еĺ�����֮һ�ռ�����ڶ������
*/
// �ã��������DZ���Ϊ���������ɲ����Ӷ�/д�������ˡ�����������Ҫ������������Ѱ�ҵ�
// һ��������ۣ��������������������̴���������ĩ�˿�ʼ����������Ҫ���ڶ�
// ������������ֱ�ӴӶ���ĩβ��ʼ������������д�����ֻ�ܴӶ���2/3�������ͷ����
// ���������롣�������ǿ�ʼ�Ӻ���ǰ������������ṹrequest���豸�ֶ�devֵ = -1ʱ��
// ��ʾ����δ��ռ�ã����У������û��һ���ǿ��еģ���ʱ����������ָ���Ѿ�����Խ��ͷ
// ��������鿴�˴������Ƿ�����ǰ��/д��READA��WRITEA���������������˴����������
// �����ñ������������˯�ߣ��Եȴ���������ڳ��������һ����������������С�
133 if (rw == READ)
134 req = request+NR_REQUEST; // ���ڶ�����ָ��ָ�����β����
135 else
136 req = request+((NR_REQUEST*2)/3); // ����д����ָ��ָ�����2/3����
137 /* find an empty request */ /* ����һ���������� */
138 while (--req >= request)
139 if (req->dev<0)
140 break;
141 /* if none found, sleep on new requests: check for rw_ahead */
/* ���û���ҵ���������øô����������˯�ߣ������Ƿ���ǰ��/д */
142 if (req < request) { // �����������ͷ�����������
143 if (rw_ahead) { // ��������ǰ��/д�������˳���
144 unlock_buffer(bh);
145 return;
146 }
147 sleep_on(&wait_for_request); // �����˯�ߣ������ٲ鿴������С�
148 goto repeat; // ��ת110�С�
149 }
150 /* fill up the request-info, and add it to the queue */
/* ���������������д������Ϣ���������������� */
// OK������ִ�е������ʾ���ҵ�һ����������� �������������úõ����������͵���
// add_request()�������ӵ���������У������˳�������ṹ��μ�blk_drv/blk.h��23�С�
// req->sector�Ƕ�д��������ʼ�����ţ�req->buffer�������������ݵĻ�������
151 req->dev = bh->b_dev; // �豸�š�
152 req->cmd = rw; // ����(READ/WRITE)��
153 req->errors=0; // ����ʱ�����Ĵ��������
154 req->sector = bh->b_blocknr<<1; // ��ʼ���������ת����������(1��=2����)��
155 req->nr_sectors = 2; // ����������Ҫ��д����������
156 req->buffer = bh->b_data; // ���������ָ��ָ�����д�����ݻ�������
157 req->waiting = NULL; // ����ȴ�����ִ����ɵĵط���
158 req->bh = bh; // �����ͷָ�롣
159 req->next = NULL; // ָ����һ�����
160 add_request(major+blk_dev,req); // ����������������(blk_dev[major],req)��
161 }
162
//// �ͼ�ҳ���д������Low Level Read Write Page����
// ��ҳ�棨4K��Ϊ��λ���ʿ��豸���ݣ���ÿ�ζ�/д8���������μ�����ll_rw_blk()������
163 void ll_rw_page(int rw, int dev, int page, char * buffer)
164 {
165 struct request * req;
166 unsigned int major = MAJOR(dev);
167
// ���ȶԺ��������ĺϷ��Խ��м�⡣����豸���豸�Ų����ڻ��߸��豸���������������
// ���ڣ�����ʾ������Ϣ�������ء������������������Ȳ��� READҲ���� WRITE�����ʾ
// �ں˳����д�����ʾ������Ϣ��ͣ����
168 if (major >= NR_BLK_DEV || !(blk_dev[major].request_fn)) {
169 printk("Trying to read nonexistent block-device\n\r");
170 return;
171 }
172 if (rw!=READ && rw!=WRITE)
173 panic("Bad block dev command, must be R/W");
// �ڲ�����������ɺ�����������ҪΪ���β����������������������Ҫ������������
// Ѱ�ҵ�һ��������ۣ��������������������̴���������ĩ�˿�ʼ���������ǿ�ʼ��
// ����ǰ������������ṹrequest���豸�ֶ�devֵ <0 ʱ����ʾ����δ��ռ�ã����У���
// ���û��һ���ǿ��еģ���ʱ����������ָ���Ѿ�����Խ��ͷ���������ñ������������˯
// �ߣ��Եȴ���������ڳ��������һ����������������С�
174 repeat:
175 req = request+NR_REQUEST; // ��ָ��ָ�����β����
176 while (--req >= request)
177 if (req->dev<0)
178 break;
179 if (req < request) {
180 sleep_on(&wait_for_request); // ˯�ߣ������ٲ鿴������С�
181 goto repeat; // ��ת��174��ȥ����������
182 }
183 /* fill up the request-info, and add it to the queue */
/* ���������������д������Ϣ���������������� */
// OK������ִ�е������ʾ���ҵ�һ����������� �����������ú���������ѵ�ǰ����
// ��Ϊ�����ж�˯���жϺ�ȥ����add_request()�������ӵ���������У�Ȼ��ֱ�ӵ���
// ���Ⱥ����õ�ǰ����˯�ߵȴ�ҳ��ӽ����豸�ж��롣���ﲻ��make_request()��������
// ֱ���˳�������������schedule()������Ϊmake_request()��������2���������ݡ�����
// ����Ҫ�Խ����豸��/д8����������Ҫ���ϳ���ʱ�䡣��˵�ǰ���̿϶���Ҫ�ȴ���˯�ߡ�
// �������ֱ�Ӿ��ý���ȥ˯���ˣ�ʡ���ڳ��������ط���Ҫ������Щ�жϲ�����
184 req->dev = dev; // �豸�š�
185 req->cmd = rw; // ����(READ/WRITE)��
186 req->errors = 0; // ��������������
187 req->sector = page<<3; // ��ʼ��д������
188 req->nr_sectors = 8; // ���������
189 req->buffer = buffer; // ���ݻ�������
190 req->waiting = current; // ��ǰ���̽��������ȴ����С�
191 req->bh = NULL; // �����ͷָ�루���ø��ٻ��壩��
192 req->next = NULL; // ��һ��������ָ�롣
193 current->state = TASK_UNINTERRUPTIBLE; // ��Ϊ�����ж�״̬��
194 add_request(major+blk_dev,req); // ����������������
195 schedule();
196 }
197
//// �ͼ����ݿ��д������Low Level Read Write Block����
// �ú����ǿ��豸����������ϵͳ�������ֵĽӿں�����ͨ����fs/buffer.c�����б����á�
// ��Ҫ�����Ǵ������豸��д��������뵽ָ�����豸��������С�ʵ�ʵĶ�д��������
// ���豸��request_fn()������ɡ�����Ӳ�̲������ú�����do_hd_request()����������
// �����ú�����do_fd_request()����������������do_rd_request()�� ���⣬�ڵ��øú�
// ��֮ǰ����������Ҫ���ȰѶ�/д���豸����Ϣ�����ڻ����ͷ�ṹ�У����豸�š���š�
// ������rw �C READ��READA��WRITE��WRITEA�����bh �C ���ݻ����ͷָ�롣
198 void ll_rw_block(int rw, struct buffer_head * bh)
199 {
200 unsigned int major; // ���豸�ţ�����Ӳ����3����
201
// ����豸���豸�Ų����ڻ��߸��豸������������������ڣ�����ʾ������Ϣ�������ء�
// ��������������������
202 if ((major=MAJOR(bh->b_dev)) >= NR_BLK_DEV ||
203 !(blk_dev[major].request_fn)) {
204 printk("Trying to read nonexistent block-device\n\r");
205 return;
206 }
207 make_request(major,rw,bh);
208 }
209
//// ���豸��ʼ���������ɳ�ʼ������main.c���á�
// ��ʼ���������飬��������������Ϊ������(dev = -1)����32��(NR_REQUEST = 32)��
210 void blk_dev_init(void)
211 {
212 int i;
213
214 for (i=0 ; i<NR_REQUEST ; i++) {
215 request[i].dev = -1;
216 request[i].next = NULL;
217 }
218 }
219
1 /*
2 * linux/kernel/blk_drv/ramdisk.c
3 *
4 * Written by Theodore Ts'o, 12/2/91
5 */
/* ��Theodore Ts'o���ƣ�12/2/91
*/
// Theodore Ts'o (Ted Ts'o)��Linux�����е��������Linux�����緶Χ�ڵ�����Ҳ������
// ��Ĺ��͡�����Linux����ϵͳ������ʱ�����ͻ��ż��������ΪLinux�ķ�չ�ṩ�˵�����
// ���б�����maillist�����ڱ�����������������Linux��ftp������վ�㣨tsx-11.mit.edu����
// ����������Ϊ���Linux�û��ṩ��������Linux�����������֮һ�������ʵ����ext2
// �ļ�ϵͳ�����ļ�ϵͳ�ѳ�ΪLinux��������ʵ�ϵ��ļ�ϵͳ������������Ƴ���ext3�ļ�
// ϵͳ�����������ļ�ϵͳ���ȶ��ԡ��ɻָ��Ժͷ���Ч�ʡ���Ϊ�������Ƴ磬��97�ڣ�2002
// ��5�£���LinuxJournal�ڿ�������Ϊ�˷�����������������˲ɷá�Ŀǰ��ΪIBM Linux
// �������Ĺ��������������й�LSB (Linux Standard Base)�ȷ���Ĺ����������ĸ�����ҳ�ǣ�
// http://thunk.org/tytso/)
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8
9 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE����ѡ�
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
11 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�Ͷ��塣
13 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵ�Ƕ��ʽ���ꡣ
14 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
15 #include <asm/memory.h> // �ڴ濽��ͷ�ļ�������memcpy()Ƕ��ʽ���꺯����
16
// ����RAM�����豸�ŷ��ų��������������������豸�ű����ڰ���blk.h�ļ�֮ǰ�����塣
// ��Ϊblk.h�ļ���Ҫ�õ�������ų���ֵ��ȷ��һЩ�е������������źͺꡣ
17 #define MAJOR_NR 1
18 #include "blk.h"
19
// ���������ڴ��е���ʼλ�á���λ�û��ڵ�52���ϳ�ʼ������rd_init()��ȷ�����μ��ں�
// ��ʼ������init/main.c����124�С�'rd'��'ramdisk'����д��
20 char *rd_start; // ���������ڴ��еĿ�ʼ��ַ��
21 int rd_length = 0; // ��������ռ�ڴ��С���ֽڣ���
22
// �����̵�ǰ���������������
// �ú����ij���ṹ��Ӳ�̵�do_hd_request()�������ƣ��μ�hd.c��294�С��ڵͼ����豸
// �ӿں���ll_rw_block()�����������̣�rd������������ӵ� rd��������֮�ͻ��
// �øú����� rd��ǰ��������д������ú������ȼ��㵱ǰ��������ָ������ʼ������Ӧ��
// ���������ڴ����ʼλ��addr ��Ҫ�����������Ӧ���ֽڳ���ֵ len��Ȼ�������������
// ��������в���������д����WRITE���Ͱ���������ָ�������е�����ֱ�Ӹ��Ƶ��ڴ�λ��
// addr�������Ƕ�������֮�����ݸ�����ɺ�ֱ�ӵ��� end_request() �Ա���������
// ������������Ȼ����ת��������ʼ����ȥ������һ�����������û�����������˳���
23 void do_rd_request(void)
24 {
25 int len;
26 char *addr;
27
// ���ȼ��������ĺϷ��ԣ�����û�����������˳����μ�blk.h����127�У���Ȼ�������
// �����������������ʼ�����������ڴ��ж�Ӧ�ĵ�ַaddr��ռ�õ��ڴ��ֽڳ���ֵlen��
// �¾�����ȡ���������е���ʼ������Ӧ���ڴ���ʼλ�ú��ڴ泤�ȡ�����sector << 9��ʾ
// sector * 512��������ֽ�ֵ��CURRENT������Ϊ (blk_dev[MAJOR_NR].current_request)��
28 INIT_REQUEST;
29 addr = rd_start + (CURRENT->sector << 9);
30 len = CURRENT->nr_sectors << 9;
// �����ǰ�����������豸�Ų�Ϊ1���߶�Ӧ�ڴ���ʼλ�ô���������ĩβ��������������
// ����ת�� repeat ��ȥ������һ���������������� repeat �����ں� INIT_REQUEST �ڣ�
// λ�ں�Ŀ�ʼ�����μ�blk.h�ļ���127�С�
31 if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {
32 end_request(0);
33 goto repeat;
34 }
// Ȼ�����ʵ�ʵĶ�д�����������д���WRITE�������������л����������ݸ��Ƶ���ַ
// addr��������Ϊlen�ֽڡ�����Ƕ����READ������addr��ʼ���ڴ����ݸ��Ƶ�������
// �������У�����Ϊlen�ֽڡ�������ʾ������ڣ�������
35 if (CURRENT-> cmd == WRITE) {
36 (void ) memcpy(addr,
37 CURRENT->buffer,
38 len);
39 } else if (CURRENT->cmd == READ) {
40 (void) memcpy(CURRENT->buffer,
41 addr,
42 len);
43 } else
44 panic("unknown ramdisk-command");
// Ȼ����������ɹ��������ø��±�־���������������豸����һ�����
45 end_request(1);
46 goto repeat;
47 }
48
49 /*
50 * Returns amount of memory which needs to be reserved.
51 */
/* �����ڴ�������ramdisk������ڴ��� */
// �����̳�ʼ��������
// �ú������������������豸�������������ָ��ָ��do_rd_request()��Ȼ��ȷ��������
// �������ڴ��е���ʼ��ַ��ռ���ֽڳ���ֵ���������������������㡣����������ȡ�
// ��linux/Makefile�ļ������ù�RAMDISKֵ��Ϊ��ʱ����ʾϵͳ�лᴴ��RAM�������豸��
// ����������µ��ں˳�ʼ�������У��������ͻᱻ���ã�init/main.c��L151�У����ú���
// �ĵ�2������length�ᱻ��ֵ��RAMDISK * 1024����λΪ�ֽڡ�
52 long rd_init(long mem_start, int length)
53 {
54 int i;
55 char *cp;
56
57 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; // do_rd_request()��
58 rd_start = (char *) mem_start; // ����16MBϵͳ��ֵΪ4MB��
59 rd_length = length; // ����������ֵ��
60 cp = rd_start;
61 for (i=0; i < length; i++) // �������㡣
62 *cp++ = '\0';
63 return(length);
64 }
65
66 /*
67 * If the root device is the ram disk, try to load it.
68 * In order to do this, the root device is originally set to the
69 * floppy, and we later change it to be ram disk.
70 */
/*
* ������ļ�ϵͳ�豸(root device)��ramdisk�Ļ������Լ�������
* root deviceԭ����ָ�����̵ģ����ǽ����ij�ָ��ramdisk��
*/
//// ���Ѹ��ļ�ϵͳ���ص��������С�
// �ú��������ں����ú���setup()��hd.c��156�У��б����á����⣬1���̿� = 1024�ֽڡ�
// ��75���ϵı���block=256��ʾ���ļ�ϵͳӳ���ļ����洢��boot�̵�256���̿鿪ʼ����
71 void rd_load(void)
72 {
73 struct buffer_head *bh; // ���ٻ����ͷָ�롣
74 struct super_block s; // �ļ�������ṹ��
75 int block = 256; /* Start at block 256 */ /* ��ʼ��256�̿� */
76 int i = 1;
77 int nblocks; // �ļ�ϵͳ�̿�������
78 char *cp; /* Move pointer */
79
// ���ȼ�������̵���Ч�Ժ������ԡ����ramdisk�ij���Ϊ�㣬���˳���������ʾramdisk
// �Ĵ�С�Լ��ڴ���ʼλ�á������ʱ���ļ��豸���������豸����Ҳ�˳���
80 if (!rd_length)
81 return;
82 printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length,
83 (int) rd_start);
84 if (MAJOR(ROOT_DEV) != 2)
85 return;
// Ȼ������ļ�ϵͳ�Ļ����������������̿�256+1��256��256+2������block+1��ָ������
// �ij����顣breada() ���ڶ�ȡָ�������ݿ飬���������Ҫ���Ŀ飬Ȼ�غ������ݿ��
// ������ָ�롣�������NULL�����ʾ���ݿ鲻�ɶ���fs/buffer.c��322����Ȼ��ѻ�������
// �Ĵ��̳����飨d_super_block�Ǵ��̳�����ṹ�����Ƶ�s�����У����ͷŻ������� ����
// ���ǿ�ʼ�Գ��������Ч�Խ����жϡ� ������������ļ�ϵͳħ�����ԣ���˵�����ص�����
// �鲻��MINIX�ļ�ϵͳ�������˳����й�MINIX������Ľṹ��μ��ļ�ϵͳһ�����ݡ�
86 bh = breada(ROOT_DEV,block+1,block,block+2,-1);
87 if (!bh) {
88 printk("Disk error while looking for ramdisk!\n");
89 return;
90 }
91 *((struct d_super_block *) &s) = *((struct d_super_block *) bh->b_data);
92 brelse(bh);
93 if (s.s_magic != SUPER_MAGIC)
94 /* No ram disk image present, assume normal floppy boot */
/* ������û��ramdiskӳ���ļ����˳�ȥִ��ͨ������������ */
95 return;
// Ȼ��������ͼ���������ļ�ϵͳ���뵽�ڴ����������С�����һ���ļ�ϵͳ��˵���䳬����
// �ṹ�� s_nzones �ֶ��б������������������Ϊ����������һ�������к��е����ݿ�
// �������ֶ�s_log_zone_sizeָ��������ļ�ϵͳ�е����ݿ�����nblocks �͵��� (����
// �� * 2^(ÿ���ο����Ĵη�))����nblocks = (s_nzones * 2^s_log_zone_size)���������
// �ļ�ϵͳ�����ݿ����������ڴ��������������ɵĿ��������������ִ�м��ز�������ֻ
// ����ʾ������Ϣ�����ء�
96 nblocks = s.s_nzones << s.s_log_zone_size;
97 if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
98 printk("Ram disk image too big! (%d blocks, %d avail)\n",
99 nblocks, rd_length >> BLOCK_SIZE_BITS);
100 return;
101 }
// �����������������ɵ����ļ�ϵͳ�����ݿ�������������ʾ�������ݿ���Ϣ������cpָ��
// �ڴ���������ʼ����Ȼ��ʼִ��ѭ�������������ϸ��ļ�ϵͳӳ���ļ����ص��������ϡ�
// �ڲ��������У����һ����Ҫ���ص��̿�������2�飬���Ǿ����ó�ǰԤ������breada()��
// �����ʹ��bread()�������е����ȡ�����ڶ��̹����г���I/O��������ֻ�ܷ�����
// �ع��̷��ء�����ȡ�Ĵ��̿��ʹ��memcpy()�����Ӹ��ٻ������и��Ƶ��ڴ���������Ӧ
// λ�ô���ͬʱ��ʾ�Ѽ��صĿ�������ʾ�ַ����еİ˽�����'\010'��ʾ��ʾһ���Ʊ�����
102 printk("Loading %d bytes into ram disk... 0000k",
103 nblocks << BLOCK_SIZE_BITS);
104 cp = rd_start;
105 while (nblocks) {
106 if (nblocks > 2) // ����ȡ��������2������ó�ǰԤ����
107 bh = breada(ROOT_DEV, block, block+1, block+2, -1);
108 else // ����͵����ȡ��
109 bh = bread(ROOT_DEV, block);
110 if (!bh) {
111 printk("I/O error on block %d, aborting load\n",
112 block);
113 return;
114 }
115 (void) memcpy(cp, bh->b_data, BLOCK_SIZE); // ���Ƶ�cp����
116 brelse(bh);
117 printk("\010\010\010\010\010%4dk",i); // ��ӡ���ؿ����ֵ��
118 cp += BLOCK_SIZE; // ������ָ��ǰ�ơ�
119 block++;
120 nblocks--;
121 i++;
122 }
// ��boot���д�256�̿鿪ʼ���������ļ�ϵͳ������Ϻ�������ʾ��done��������Ŀǰ
// ���ļ��豸���ij������̵��豸��0x0101����ء�
123 printk("\010\010\010\010\010done \n");
124 ROOT_DEV=0x0101;
125 }
126
1 /*
2 * linux/kernel/floppy.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 02.12.91 - Changed to static variables to indicate need for reset
9 * and recalibrate. This makes some things easier (output_byte reset
10 * checking etc), and means less interrupt jumping in case of errors,
11 * so the code is hopefully easier to understand.
12 */
/*
* 02.12.91 - �ijɾ�̬����������Ӧ��λ������У����������ʹ��ijЩ����
* ��������Ϊ���㣨output_byte ��λ���ȣ���������ζ���ڳ���ʱ�ж���ת
* Ҫ��һЩ������Ҳϣ�������ܸ����ױ����⡣
*/
13
14 /*
15 * This file is certainly a mess. I've tried my best to get it working,
16 * but I don't like programming floppies, and I have only one anyway.
17 * Urgel. I should check for more errors, and do more graceful error
18 * recovery. Seems there are problems with several drives. I've tried to
19 * correct them. No promises.
20 */
/*
* ����ļ���Ȼ�Ƚϻ��ҡ����Ѿ���������ʹ���ܹ����������Ҳ�ϲ��������̣�
* ������Ҳֻ��һ�����������⣬��Ӧ��������IJ���������Լ���������Ĵ���
* ����ijЩ�����������������������һЩ���⡣���Ѿ������Ž��о����ˣ�
* �����ܱ�֤��������ʧ��
*/
21
22 /*
23 * As with hd.c, all routines within this file can (and will) be called
24 * by interrupts, so extreme caution is needed. A hardware interrupt
25 * handler may not sleep, or a kernel panic will happen. Thus I cannot
26 * call "floppy-on" directly, but have to set a special timer interrupt
27 * etc.
28 *
29 * Also, I'm not certain this works on more than 1 floppy. Bugs may
30 * abund.
31 */
/*
* ��ͬhd.c�ļ�һ�������ļ��е������ӳ����ܹ����жϵ��ã�������Ҫ�ر�
* ��С�ġ�Ӳ���жϴ��������Dz���˯�ߵģ������ں˾ͻ�ɵ��(����)J����˲���
* ֱ�ӵ���"floppy-on"����ֻ������һ������Ķ�ʱ�жϵȡ�
*
* ���⣬�Ҳ��ܱ�֤�ó������ڶ���1��������ϵͳ�Ϲ������п��ܴ��ڴ���
*/
32
33 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
34 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ������ļ����ṹ��file��m_inode���ȡ�
35 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
36 #include <linux/fdreg.h> // ����ͷ�ļ����������̿�����������һЩ���塣
37 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ����ꡣ
38 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
39 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
40
// �����������豸�ŷ��ų����������������У����豸�ű����ڰ���blk.h�ļ�֮ǰ�����塣
// ��Ϊblk.h�ļ���Ҫ�õ�������ų���ֵ��ȷ��һЩ��������ط��ų����ͺꡣ
41 #define MAJOR_NR 2 // ���������豸����2��
42 #include "blk.h" // ���豸ͷ�ļ�����������ṹ�����豸�ṹ�ͺ꺯������Ϣ��
43
44 static int recalibrate = 0; // ��־��1��ʾ��Ҫ����У����ͷλ�ã���ͷ���������
45 static int reset = 0; // ��־��1��ʾ��Ҫ���и�λ������
46 static int seek = 0; // ��־��1��ʾ��Ҫִ��Ѱ��������
47
// ��ǰ��������Ĵ���DOR��Digital Output Register����������kernel/sched.c��223�С�
// �ñ����������������е���Ҫ��־������ѡ�����������Ƶ��������������λ���̿�������
// ������/��ֹDMA���ж�������μ������б����DOR�Ĵ�����˵����
48 extern unsigned char current_DOR;
49
// �ֽ�ֱ���������Ƕ����꣩����ֵval�����port�˿ڡ�
50 #define immoutb_p(val,port) \
51 __asm__("outb %0,%1\n\tjmp 1f\n1:\tjmp 1f\n1:"::"a" ((char) (val)),"i" (port))
52
// �������궨�����ڼ����������豸�š�
// ����x�Ǵ��豸�š����豸�� = TYPE*4 + DRIVE�����㷽���μ��б���
53 #define TYPE(x) ((x)>>2) // �������ͣ�2--1.2Mb��7--1.44Mb����
54 #define DRIVE(x) ((x)&0x03) // ������ţ�0--3��ӦA--D����
55 /*
56 * Note that MAX_ERRORS=8 doesn't imply that we retry every bad read
57 * max 8 times - some types of errors increase the errorcount by 2,
58 * so we might actually retry only 5-6 times before giving up.
59 */
/*
* ע�⣬���涨��MAX_ERRORS=8������ʾ��ÿ�ζ����������8�� - ��Щ����
* �Ĵ����ѳ�������ֵ��2����������ʵ�����ڷ�������֮ǰֻ�賢��5-6�鼴�ɡ�
*/
60 #define MAX_ERRORS 8
61
62 /*
63 * globals used by 'result()'
64 */
/* �����Ǻ���'result()'ʹ�õ�ȫ�ֱ��� */
// ��Щ״̬�ֽ��и�����λ�ĺ�����μ�include/linux/fdreg.hͷ�ļ������μ��б���˵����
65 #define MAX_REPLIES 7 // FDC����7�ֽڵĽ����Ϣ��
66 static unsigned char reply_buffer[MAX_REPLIES]; // ���FDC���ص�Ӧ������Ϣ��
67 #define ST0 (reply_buffer[0]) // ���״̬�ֽ�0��
68 #define ST1 (reply_buffer[1]) // ���״̬�ֽ�1��
69 #define ST2 (reply_buffer[2]) // ���״̬�ֽ�2��
70 #define ST3 (reply_buffer[3]) // ���״̬�ֽ�3��
71
72 /*
73 * This struct defines the different floppy types. Unlike minix
74 * linux doesn't have a "search for right type"-type, as the code
75 * for that is convoluted and weird. I've got enough problems with
76 * this driver as it is.
77 *
78 * The 'stretch' tells if the tracks need to be boubled for some
79 * types (ie 360kB diskette in 1.2MB drive etc). Others should
80 * be self-explanatory.
81 */
/*
* ��������̽ṹ�����˲�ͬ���������͡���minix��ͬ���ǣ�Linuxû��
* "������ȷ������"-���ͣ���Ϊ���䴦���Ĵ������˷ѽ��ҹֵֹġ�������
* �Ѿ���������̫��������ˡ�
*
* ��ijЩ���͵����̣�������1.2MB�������е�360kB���̵ȣ���'stretch'
* ���ڼ��ŵ��Ƿ���Ҫ���������������Ӧ���������ġ�
*/
// �������̽ṹ�����̲����У�
// size ��С(������)��
// sect ÿ�ŵ���������
// head ��ͷ����
// track �ŵ�����
// stretch �Դŵ��Ƿ�Ҫ���������־����
// gap ������϶����(�ֽ���)��
// rate ���ݴ������ʣ�
// spec1 ��������4λ�������ʣ�����λ��ͷж��ʱ�䣩��
82 static struct floppy_struct {
83 unsigned int size, sect, head, track, stretch;
84 unsigned char gap,rate,spec1;
85 } floppy_type[] = {
86 { 0, 0,0, 0,0,0x00,0x00,0x00 }, /* no testing */
87 { 720, 9,2,40,0,0x2A,0x02,0xDF }, /* 360kB PC diskettes */
88 { 2400,15,2,80,0,0x1B,0x00,0xDF }, /* 1.2 MB AT-diskettes */
89 { 720, 9,2,40,1,0x2A,0x02,0xDF }, /* 360kB in 720kB drive */
90 { 1440, 9,2,80,0,0x2A,0x02,0xDF }, /* 3.5" 720kB diskette */
91 { 720, 9,2,40,1,0x23,0x01,0xDF }, /* 360kB in 1.2MB drive */
92 { 1440, 9,2,80,0,0x23,0x01,0xDF }, /* 720kB in 1.2MB drive */
93 { 2880,18,2,80,0,0x1B,0x00,0xCF }, /* 1.44MB diskette */
94 };
95
96 /*
97 * Rate is 0 for 500kb/s, 2 for 300kbps, 1 for 250kbps
98 * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
99 * H is head unload time (1=16ms, 2=32ms, etc)
100 *
101 * Spec2 is (HLD<<1 | ND), where HLD is head load time (1=2ms, 2=4 ms etc)
102 * and ND is set means no DMA. Hardcoded to 6 (HLD=6ms, use DMA).
103 */
/*
* ��������rate��0��ʾ500kbps��1��ʾ300kbps��2��ʾ250kbps��
* ����spec1��0xSH������S�Dz������ʣ�F-1ms��E-2ms��D=3ms�ȣ���
* H�Ǵ�ͷж��ʱ�䣨1=16ms��2=32ms�ȣ�
*
* spec2�ǣ�HLD<<1 | ND��������HLD�Ǵ�ͷ����ʱ�䣨1=2ms��2=4ms�ȣ�
* ND��λ��ʾ��ʹ��DMA��No DMA�����ڳ�����Ӳ�����6��HLD=6ms��ʹ��DMA����
*/
// ע�⣬������ͷ����ʱ�����дHLD���д�ɱ���HLT��Head Load Time����
104
// floppy_interrupt()��sys_call.s�����������жϴ������̱�š����ォ�����̳�ʼ��
// ����floppy_init()����469�У�ʹ������ʼ���ж���������������
105 extern void floppy_interrupt(void);
// ����boot/head.s��132�д��������ʱ���̻����������������Ļ����������ڴ�1MB
// ����ij���ط�������Ҫ��DMA������������ʱ����������Ϊ8237AоƬֻ����1MB��
// ַ��Χ��Ѱַ��
106 extern char tmp_floppy_area[1024];
107
108 /*
109 * These are global variables, as that's the easiest way to give
110 * information to interrupts. They are the data used for the current
111 * request.
112 */
/*
* ������һЩȫ�ֱ�������Ϊ���ǽ���Ϣ�����жϳ�����ķ�ʽ������
* ���ڵ�ǰ����������ݡ�
*/
// ��Щ��ν�ġ�ȫ�ֱ�������ָ�������жϴ��������е��õ�C����ʹ�õı�������Ȼ��Щ
// C�������ڱ������ڡ�
113 static int cur_spec1 = -1; // ��ǰ���̲���spec1��
114 static int cur_rate = -1; // ��ǰ����ת��rate��
115 static struct floppy_struct * floppy = floppy_type; // �������ͽṹ����ָ�롣
116 static unsigned char current_drive = 0; // ��ǰ�������š�
117 static unsigned char sector = 0; // ��ǰ�����š�
118 static unsigned char head = 0; // ��ǰ��ͷ�š�
119 static unsigned char track = 0; // ��ǰ�ŵ��š�
120 static unsigned char seek_track = 0; // Ѱ���ŵ��š�
121 static unsigned char current_track = 255; // ��ǰ��ͷ���ڴŵ��š�
122 static unsigned char command = 0; // ��/��
123 unsigned char selected = 0; // ������ѡ����־���ڴ���������֮ǰҪ����ѡ��������
124 struct task_struct * wait_on_floppy_select = NULL; // �ȴ�ѡ��������������С�
125
//// ȡ��ѡ��������
// �����������ָ��������nr��ǰ��û�б�ѡ��������ʾ������Ϣ��Ȼ��λ������ѡ����־
// selected�������ѵȴ�ѡ���������������������Ĵ���(DOR)�ĵ�2λ����ָ��ѡ�����
// ����0-3��ӦA-D����
126 void floppy_deselect(unsigned int nr)
127 {
128 if (nr != (current_DOR & 3))
129 printk("floppy_deselect: drive not selected\n\r");
130 selected = 0; // ��λ������ѡ����־��
131 wake_up(&wait_on_floppy_select); // ���ѵȴ�������
132 }
133
134 /*
135 * floppy-change is never called from an interrupt, so we can relax a bit
136 * here, sleep etc. Note that floppy-on tries to set current_DOR to point
137 * to the desired drive, but it will probably not survive the sleep if
138 * several floppies are used at the same time: thus the loop.
139 */
/*
* floppy-change()���Ǵ��жϳ����е��õģ������������ǿ�������һ�£�˯�ߵȡ�
* ע��floppy-on()�᳢������current_DORָ�������������������ͬʱʹ�ü���
* ����ʱ����˯�ߣ���˴�ʱֻ��ʹ��ѭ����ʽ��
*/
//// ���ָ�����������̸��������
// ����nr�������š�������̸�������1������0��
// �ú�������ѡ������ָ��������nr��Ȼ��������̿���������������Ĵ���DIR��ֵ������
// ���������е������Ƿ��������ú����ɳ���fs/buffer.c�е� check_disk_change()��
// �����ã���119�У���
140 int floppy_change(unsigned int nr)
141 {
// ����Ҫ��������������ת�������ﵽ��������ת�١�����Ҫ����һ��ʱ�䡣���õķ�������
// ��kernel/sched.c�����̶�ʱ����do_floppy_timer()����һ������ʱ������floppy_on()
// �����������ж���ʱ�Ƿ�mon_timer[nr]==0?������û�е����õ�ǰ���̼���˯�ߵȴ���
// ����ʱ����do_floppy_timer()�ỽ�ѵ�ǰ���̡�
142 repeat:
143 floppy_on(nr); // �������ȴ�ָ������nr��kernel/sched.c����251�У���
// ��������������ת��֮���������鿴һ�µ�ǰѡ��������Dz��Ǻ�������ָ��������nr��
// �����ǰѡ�����������ָ��������nr�������Ѿ�ѡ�����������������õ�ǰ��������
// �жϵȴ�״̬���Եȴ�����������ȡ��ѡ�����μ�����floppy_deselect()�� �����ǰû
// ��ѡ������������������������ȡ��ѡ����ʹ��ǰ������ʱ�� ��ǰ������Ȼ����ָ��
// ������nr������ת��������ʼ������ѭ���ȴ���
144 while ((current_DOR & 3) != nr && selected)
145 sleep_on(&wait_on_floppy_select);
146 if ((current_DOR & 3) != nr)
147 goto repeat;
// �������̿�������ѡ������ָ��������nr������ȡ��������Ĵ���DIR��ֵ����������
// λ��λ7����λ�����ʾ�����Ѹ�������ʱ���ɹر����ﲢ����1�˳��� ����ر����ﷵ
// ��0�˳�����ʾ����û�б�������
148 if (inb(FD_DIR) & 0x80) {
149 floppy_off(nr);
150 return 1;
151 }
152 floppy_off(nr);
153 return 0;
154 }
155
//// �����ڴ滺��飬��1024�ֽڡ�
// ���ڴ��ַfrom������1024�ֽ����ݵ���ַto����
156 #define copy_buffer(from,to) \
157 __asm__("cld ; rep ; movsl" \
158 ::"c" (BLOCK_SIZE/4),"S" ((long)(from)),"D" ((long)(to)) \
159 :"cx","di","si")
160
//// ���ã���ʼ��������DMAͨ����
// ���������ݶ�д������ʹ��DMA���еġ������ÿ�ν������ݴ���֮ǰ��Ҫ����DMAоƬ
// ��ר������������ͨ��2���й�DMA��̷�����μ������б������Ϣ��
161 static void setup_DMA(void)
162 {
163 long addr = (long) CURRENT->buffer; // ��ǰ��������������ڴ��ַ��
164
// ���ȼ��������Ļ���������λ�á���������������ڴ�1MB���ϵ�ij���ط�������Ҫ��
// DMA������������ʱ��������tmp_floppy_area��������Ϊ8237AоƬֻ����1MB��ַ��
// Χ��Ѱַ�������д���������Ҫ�����ݴ�������������Ƶ�����ʱ����
165 cli();
166 if (addr >= 0x100000) {
167 addr = (long) tmp_floppy_area;
168 if (command == FD_WRITE)
169 copy_buffer(CURRENT->buffer,tmp_floppy_area);
170 }
// ���������ǿ�ʼ����DMAͨ��2���ڿ�ʼ����֮ǰ��Ҫ�����θ�ͨ������ͨ�����μĴ���
// �˿�Ϊ0x0A��λ0-1ָ��DMAͨ��(0--3)��λ2��1��ʾ���Σ�0��ʾ�������� Ȼ����
// DMA�������˿�12��11д�뷽ʽ�֣�������0x46��д������0x4A���� ��д�봫��ʹ��
// ��������ַaddr����Ҫ������ֽ���0x3ff��0--1023�������λ��DMAͨ��2�����Σ�
// ����DMA2����DREQ�źš�
171 /* mask DMA 2 */ /* ����DMAͨ��2 */
172 immoutb_p(4|2,10);
173 /* output command byte. I don't know why, but everyone (minix, */
174 /* sanches & canton) output this twice, first to 12 then to 11 */
/* ��������ֽڡ����Dz�֪��Ϊʲô������ÿ���ˣ�minix��*/
/* sanches��canton����������Σ�������12�ڣ�Ȼ����11�� */
// ����Ƕ���������DMA�������ġ�����Ⱥ������˿�12�ͷ�ʽ�Ĵ����˿�11д��
// ��ʽ�֣�����ʱ��0x46��д����0x4A����
// ���ڸ�ͨ���ĵ�ַ�ͼ����Ĵ�������16λ�ģ��������������ʱ����Ҫ��2�ν��в�����
// һ�η��ʵ��ֽڣ���һ�η��ʸ��ֽڡ���ʵ����д�ĸ��ֽ������Ⱥ�����״̬������
// ��������Ϊ0ʱ������ʵ��ֽڣ����ֽڴ�����Ϊ1ʱ������ʸ��ֽڡ�ÿ����һ�Σ�
// �ô�������״̬�ͱ仯һ�Ρ���д�˿�12�Ϳ��Խ��������ó�0״̬���Ӷ���16λ�Ĵ�
// �������ôӵ��ֽڿ�ʼ��
175 __asm__("outb %%al,$12\n\tjmp 1f\n1:\tjmp 1f\n1:\t"
176 "outb %%al,$11\n\tjmp 1f\n1:\tjmp 1f\n1:"::
177 "a" ((char) ((command == FD_READ)?DMA_READ:DMA_WRITE)));
178 /* 8 low bits of addr */ /* ��ַ��0-7λ */
// ��DMAͨ��2д���/��ǰ��ַ�Ĵ������˿�4����
179 immoutb_p(addr,4);
180 addr >>= 8;
181 /* bits 8-15 of addr */ /* ��ַ��8-15λ */
182 immoutb_p(addr,4);
183 addr >>= 8;
184 /* bits 16-19 of addr */ /* ��ַ16-19λ */
// DMAֻ������1MB�ڴ�ռ���Ѱַ�����16-19λ��ַ�����ҳ��Ĵ���(�˿�0x81)��
185 immoutb_p(addr,0x81);
186 /* low 8 bits of count-1 (1024-1=0x3ff) */ /* ��������8λ(1024-1 = 0x3ff) */
// ��DMAͨ��2д���/��ǰ�ֽڼ�����ֵ���˿�5����
187 immoutb_p(0xff,5);
188 /* high 8 bits of count-1 */ /* ��������8λ */
// һ�ι�����1024�ֽڣ�������������
189 immoutb_p(3,5);
190 /* activate DMA 2 */ /* ����DMAͨ��2������ */
191 immoutb_p(0|2,10);
192 sti();
193 }
194
//// ���������������һ���ֽ�����������
// �������������һ���ֽ�֮ǰ����������Ҫ��������״̬���������ݴ��䷽���������
// �ɴ�CPU �� FDC����˺�����Ҫ���ȶ�ȡ������״̬��Ϣ������ʹ����ѭ����ѯ��ʽ����
// ���ʵ���ʱ����������������ø�λ��־reset��
195 static void output_byte(char byte)
196 {
197 int counter;
198 unsigned char status;
199
// ѭ����ȡ��״̬������FD_STATUS��0x3f4����״̬���������״̬�� STATUS_READY ����
// ����λSTATUS_DIR = 0��CPU��FDC�����������ݶ˿����ָ���ֽڡ�
200 if (reset)
201 return;
202 for(counter = 0 ; counter < 10000 ; counter++) {
203 status = inb_p(FD_STATUS) & (STATUS_READY | STATUS_DIR);
204 if (status == STATUS_READY) {
205 outb(byte,FD_DATA);
206 return;
207 }
208 }
// �����ѭ��1��ν��������ܷ��ͣ����ø�λ��־������ӡ������Ϣ��
209 reset = 1;
210 printk("Unable to send byte to FDC\n\r");
211 }
212
//// ��ȡFDCִ�еĽ����Ϣ��
// �����Ϣ���7���ֽڣ����������reply_buffer[]�С����ض���Ľ���ֽ�����������
// ֵ = -1�����ʾ��������������ʽ�����溯�����ơ�
213 static int result(void)
214 {
215 int i = 0, counter, status;
216
// ����λ��־����λ���������˳���ȥִ�к��������еĸ�λ����������ѭ����ȡ��״̬��
// ����FD_STATUS��0x3f4����״̬�������ȡ�Ŀ�����״̬��READY����ʾ�Ѿ�û�����ݿ�
// ȡ�����Ѷ�ȡ���ֽ���i�����������״̬�Ƿ����־��λ��CPUßFDC���������á�
// æ����ʾ�����ݿɶ�ȡ�� ���ǰѿ������еĽ�����ݶ��뵽Ӧ���������С� ����ȡ
// MAX_REPLIES��7�����ֽڡ�
217 if (reset)
218 return -1;
219 for (counter = 0 ; counter < 10000 ; counter++) {
220 status = inb_p(FD_STATUS)&(STATUS_DIR|STATUS_READY|STATUS_BUSY);
221 if (status == STATUS_READY)
222 return i;
223 if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
224 if (i >= MAX_REPLIES)
225 break;
226 reply_buffer[i++] = inb_p(FD_DATA);
227 }
228 }
// �����ѭ��1��ν��������ܷ��ͣ����ø�λ��־������ӡ������Ϣ��
229 reset = 1;
230 printk("Getstatus times out\n\r");
231 return -1;
232 }
233
//// ���̶�д��������������
// �ú����������̶�д����������ȷ����Ҫ��ȡ�Ľ�һ���ж��������ǰ���������������
// �������ڹ涨������������MAX_ERRORS��8�Σ������ٶԵ�ǰ����������һ���IJ���
// ���ԡ������/д���������Ѿ�����MAX_ERRORS/2������Ҫ����������λ��������������
// ��λ��־reset�������������������������ֵ��һ�룬��ֻ������У��һ�´�ͷλ�ã�
// ������������У����־recalibrate�������ĸ�λ������У���������ں����ij����н��С�
234 static void bad_flp_intr(void)
235 {
// ���Ȱѵ�ǰ���������������1�������ǰ������������������������������������ȡ
// ��ѡ����ǰ�����������������������������û�б����£���
236 CURRENT->errors++;
237 if (CURRENT->errors > MAX_ERRORS) {
238 floppy_deselect(current_drive);
239 end_request(0);
240 }
// �����ǰ����������������������������������һ�룬���ø�λ��־������������и�
// λ������Ȼ�����ԡ���������������У��һ�����ԡ�
241 if (CURRENT->errors > MAX_ERRORS/2)
242 reset = 1;
243 else
244 recalibrate = 1;
245 }
246
247 /*
248 * Ok, this interrupt is called after a DMA read/write has succeeded,
249 * so we check the results, and copy any buffers.
250 */
/*
* OK��������жϴ�����������DMA��/д�ɹ�����õģ��������ǾͿ��Լ��
* ִ�н���������ƻ������е����ݡ�
*/
//// ���̶�д�����жϵ��ú�����
// �ú��������������������������������жϴ��������б����á��������ȶ�ȡ�������״
// ̬��Ϣ���ݴ��жϲ����Ƿ�������Ⲣ����Ӧ������ �����/д�����ɹ�����ô��������
// �Ƕ����������仺�������ڴ�1MB����λ�ã�����Ҫ�����ݴ�������ʱ���������Ƶ�����
// ���������
251 static void rw_interrupt(void)
252 {
// ��ȡFDCִ�еĽ����Ϣ��������ؽ���ֽ���������7������״̬�ֽ�0��1��2�д���
// ������־����ô����д��������ʾ������Ϣ���ͷŵ�ǰ����������������ǰ���������
// ��ִ�г�������������Ȼ�����ִ���������������������״̬�ĺ���μ�fdreg.h�ļ���
// ( 0xf8 = ST0_INTR | ST0_SE | ST0_ECE | ST0_NR )
// ( 0xbf = ST1_EOC | ST1_CRC | ST1_OR | ST1_ND | ST1_WP | ST1_MAM��Ӧ����0xb7)
// ( 0x73 = ST2_CM | ST2_CRC | ST2_WC | ST2_BC | ST2_MAM )
253 if (result() != 7 || (ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73)) {
254 if (ST1 & 0x02) { // 0x02 = ST1_WP - Write Protected��
255 printk("Drive %d is write protected\n\r",current_drive);
256 floppy_deselect(current_drive);
257 end_request(0);
258 } else
259 bad_flp_intr();
260 do_fd_request();
261 return;
262 }
// �����ǰ������Ļ�����λ��1MB��ַ���ϣ���˵���˴����̶����������ݻ�������ʱ��
// �����ڣ���Ҫ���Ƶ���ǰ������Ļ������У���ΪDMAֻ����1MB��ַ��ΧѰַ�������
// �ͷŵ�ǰ������ȡ��ѡ������ִ�е�ǰ������������������ѵȴ���������Ľ��У�����
// �ȴ�����������Ľ��̣����еĻ������������豸������������ɾ����������ټ���ִ
// ���������������������
263 if (command == FD_READ && (unsigned long)(CURRENT->buffer) >= 0x100000)
264 copy_buffer(tmp_floppy_area,CURRENT->buffer);
265 floppy_deselect(current_drive);
266 end_request(1);
267 do_fd_request();
268 }
269
//// ����DMAͨ��2�������̿������������Ͳ��������1�ֽ����� + 0~7�ֽڲ�������
// ��reset��־û����λ����ô�ڸú����˳��������̿�����ִ������Ӧ��/д������ͻ�
// ����һ�������ж�������ʼִ�������жϴ�������
270 inline void setup_rw_floppy(void)
271 {
272 setup_DMA(); // ��ʼ������DMAͨ����
273 do_floppy = rw_interrupt; // �������жϵ��ú���ָ�롣
274 output_byte(command); // ���������ֽڡ�
275 output_byte(head<<2 | current_drive); // ��������ͷ��+�������š�
276 output_byte(track); // �������ŵ��š�
277 output_byte(head); // ��������ͷ�š�
278 output_byte(sector); // ��������ʼ�����š�
279 output_byte(2); /* sector size = 512 */ // ������(N=2)512�ֽڡ�
280 output_byte(floppy->sect); // ������ÿ�ŵ���������
281 output_byte(floppy->gap); // ����������������ȡ�
282 output_byte(0xFF); /* sector size (0xff when n!=0 ?) */
// ��������N=0ʱ������������ֽڳ��ȣ��������á�
// �������κ�һ��output_byte()����������������ø�λ��־reset����ʱ��������ȥִ��
// do_fd_request()�еĸ�λ�������롣
283 if (reset)
284 do_fd_request();
285 }
286
287 /*
288 * This is the routine called after every seek (or recalibrate) interrupt
289 * from the floppy controller. Note that the "unexpected interrupt" routine
290 * also does a recalibrate, but doesn't come here.
291 */
/*
* ���ӳ�������ÿ�����̿�����Ѱ����������У�����ж��б����õġ�ע��
* "unexpected interrupt"(�����ж�)�ӳ���Ҳ��ִ������У�������������ڴ˵ء�
*/
//// Ѱ�������������жϹ����е��õ�C������
// ���ȷ��ͼ���ж�״̬������״̬��ϢST0�ʹ�ͷ���ڴŵ���Ϣ����������ִ�д���
// ����������ȡ���������̲���������������״̬��Ϣ���õ�ǰ�ŵ�������Ȼ���
// �ú���setup_rw_floppy()����DMA��������̶�д����Ͳ�����
292 static void seek_interrupt(void)
293 {
// ���ȷ��ͼ���ж�״̬����Ի�ȡѰ������ִ�еĽ��������������������ؽ����
// Ϣ�������ֽڣ�ST0�ʹ�ͷ��ǰ�ŵ��š�Ȼ���ȡFDCִ�еĽ����Ϣ�� ������ؽ����
// ����������2������ST0��ΪѰ�����������ߴ�ͷ���ڴŵ���ST1���������趨�ŵ�����˵
// �������˴�������ִ�м��������������Ȼ�����ִ�������������ִ�и�λ������
294 /* sense drive status */ /* ���������״̬ */
295 output_byte(FD_SENSEI);
296 if (result() != 2 || (ST0 & 0xF8) != 0x20 || ST1 != seek_track) {
297 bad_flp_intr();
298 do_fd_request();
299 return;
300 }
// ��Ѱ�������ɹ��������ִ�е�ǰ����������̲������������̿�������������Ͳ�����
301 current_track = ST1; // ���õ�ǰ�ŵ���
302 setup_rw_floppy(); // ����DMA��������̲�������Ͳ�����
303 }
304
305 /*
306 * This routine is called when everything should be correctly set up
307 * for the transfer (ie floppy motor is on and the correct floppy is
308 * selected).
309 */
/*
* �ú������ڴ��������������Ϣ����ȷ���úú��õģ������������ѿ���
* ������ѡ������ȷ�����̣���������
*/
//// ��д���ݴ��亯����
310 static void transfer(void)
311 {
// ���ȼ�鵱ǰ�����������Ƿ����ָ���������IJ����������Ǿͷ���������������������
// ����Ӧ����������1����4λ�������ʣ�����λ��ͷж��ʱ�䣻����2����ͷ����ʱ�䣩��
// Ȼ���жϵ�ǰ���ݴ��������Ƿ���ָ����������һ�£������Ǿͷ���ָ������������ֵ��
// ���ݴ������ʿ��ƼĴ���(FD_DCR)��
312 if (cur_spec1 != floppy->spec1) { // ��ǰ������
313 cur_spec1 = floppy->spec1;
314 output_byte(FD_SPECIFY); // �������ô��̲������
315 output_byte(cur_spec1); /* hut etc */ // ���Ͳ�����
316 output_byte(6); /* Head load time =6ms, DMA */
317 }
318 if (cur_rate != floppy->rate) // ��ǰ���ʡ�
319 outb_p(cur_rate = floppy->rate,FD_DCR);
// �������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ���������
// ������Ҫ���һ��reset��־����reset��ı���λ�ˣ�������ȥִ��do_fd_request()
// �еĸ�λ�������롣
320 if (reset) {
321 do_fd_request();
322 return;
323 }
// �����ʱѰ����־Ϊ�㣨������ҪѰ������������DMA�������̿�����������Ӧ��������
// �Ͳ����ء������ִ��Ѱ�����������������������жϴ������ú���ΪѰ���жϺ�����
// �����ʼ�ŵ��Ų����������ʹ�ͷѰ������Ͳ�������ʹ�õIJ������ǵ�112--121��
// �����õ�ȫ�ֱ���ֵ�������ʼ�ŵ���seek_trackΪ0����ִ������У�������ô�ͷ����
// �
324 if (!seek) {
325 setup_rw_floppy(); // ������������顣
326 return;
327 }
328 do_floppy = seek_interrupt; // Ѱ���жϵ��õ�C������
329 if (seek_track) { // ��ʼ�ŵ��š�
330 output_byte(FD_SEEK); // ���ʹ�ͷѰ�����
331 output_byte(head<<2 | current_drive);// ���Ͳ�������ͷ��+��ǰ�����š�
332 output_byte(seek_track); // ���Ͳ������ŵ��š�
333 } else {
334 output_byte(FD_RECALIBRATE); // ��������У�������ͷ���㣩��
335 output_byte(head<<2 | current_drive);// ���Ͳ�������ͷ��+��ǰ�����š�
336 }
// ͬ���أ��������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ��
// ��reset��ı���λ�ˣ�������ȥִ��do_fd_request()�еĸ�λ�������롣
337 if (reset)
338 do_fd_request();
339 }
340
341 /*
342 * Special case - used after a unexpected interrupt (or reset)
343 */
/*
* ������� - ���������жϣ���λ��������
*/
//// ��������У���жϵ��ú�����
// ���ȷ��ͼ���ж�״̬�����������������ؽ���������������ø�λ��־����������
// У����־���㡣Ȼ���ٴ�ִ���������������������Ӧ������
344 static void recal_interrupt(void)
345 {
346 output_byte(FD_SENSEI); // ���ͼ���ж�״̬���
347 if (result()!=2 || (ST0 & 0xE0) == 0x60) // ������ؽ���ֽ���������2������
348 reset = 1; // �쳣���������ø�λ��־��
349 else
350 recalibrate = 0; // ����λ����У����־��
351 do_fd_request(); // ����Ӧ������
352 }
353
//// ���������ж����������������жϴ��������е��õĺ�����
// ���ȷ��ͼ���ж�״̬�����������������ؽ���������������ø�λ��־������������
// У����־��
354 void unexpected_floppy_interrupt(void)
355 {
356 output_byte(FD_SENSEI); // ���ͼ���ж�״̬���
357 if (result()!=2 || (ST0 & 0xE0) == 0x60) // ������ؽ���ֽ���������2������
358 reset = 1; // �쳣���������ø�λ��־��
359 else
360 recalibrate = 1; // ����������У����־��
361 }
362
//// ��������������������
// �����̿�����FDC��������У������Ͳ���������λ����У����־�������̿�����ִ����
// ����У������ͻ����������������ж��е���recal_interrupt()������
363 static void recalibrate_floppy(void)
364 {
365 recalibrate = 0; // ��λ����У����־��
366 current_track = 0; // ��ǰ�ŵ��Ź��㡣
367 do_floppy = recal_interrupt; // ָ������У���жϵ��õ�C������
368 output_byte(FD_RECALIBRATE); // �����������
369 output_byte(head<<2 | current_drive); // ��������ͷ�� + ��ǰ�������š�
// �������κ�һ��output_byte()����ִ�г�������λ��־reset�ͻᱻ��λ���������
// ������Ҫ���һ��reset��־����reset��ı���λ�ˣ�������ȥִ��do_fd_request()
// �еĸ�λ�������롣
370 if (reset)
371 do_fd_request();
372 }
373
//// ���̿�����FDC��λ�жϵ��ú�����
// �ú�������������������˸�λ��������������������жϴ��������б����á�
// ���ȷ��ͼ���ж�״̬�����������Ȼ��������صĽ���ֽڡ����ŷ����趨����
// �����������ز���������ٴε��������������do_fd_request() ȥִ������У��
// ������������ִ��output_byte() ��������ʱ��λ��־�ֻᱻ��λ�����Ҳ�����ٴ�ȥ
// ִ�и�λ������
374 static void reset_interrupt(void)
375 {
376 output_byte(FD_SENSEI); // ���ͼ���ж�״̬���
377 (void) result(); // ��ȡ����ִ�н���ֽڡ�
378 output_byte(FD_SPECIFY); // �����趨�����������
379 output_byte(cur_spec1); /* hut etc */ // ���Ͳ�����
380 output_byte(6); /* Head load time =6ms, DMA */
381 do_fd_request(); // ����ִ����������
382 }
383
384 /*
385 * reset is done by pulling bit 2 of DOR low for a while.
386 */
/* FDC��λ��ͨ������������Ĵ���(DOR)λ2��0һ���ʵ�ֵ� */
//// ��λ���̿�������
// �ú����������ò����ͱ�־���Ѹ�λ��־��0��Ȼ�����������cur_spec1��cur_rate
// ��Ϊ��Ч����Ϊ��λ��������������������Ҫ�������á�����������Ҫ����У����־��
// ������FDCִ�и�λ�����������������ж��е��õ�C����reset_interrupt()�����
// ��DOR�Ĵ���λ2��0һ����Զ�����ִ�и�λ��������ǰ��������Ĵ���DOR��λ2
// ������/������
387 static void reset_floppy(void)
388 {
389 int i;
390
391 reset = 0; // ��λ��־��0��
392 cur_spec1 = -1; // ʹ��Ч��
393 cur_rate = -1;
394 recalibrate = 1; // ����У����־��λ��
395 printk("Reset-floppy called\n\r"); // ��ʾִ�����̸�λ������Ϣ��
396 cli(); // ���жϡ�
397 do_floppy = reset_interrupt; // �������жϴ��������е��õĺ�����
398 outb_p(current_DOR & ~0x04,FD_DOR); // �����̿�����FDCִ�и�λ������
399 for (i=0 ; i<100 ; i++) // �ղ������ӳ١�
400 __asm__("nop");
401 outb(current_DOR,FD_DOR); // ���������̿�������
402 sti(); // ���жϡ�
403 }
404
//// ����������ʱ�жϵ��ú�����
// ��ִ��һ��������Ҫ��IJ���֮ǰ��Ϊ�˵ȴ�ָ������������ת�������������Ĺ���ת�٣�
// do_fd_request()����Ϊ���õĵ�ǰ������������һ����ʱ��ʱ�������������Ǹö�ʱ��
// ����ʱ���õĺ����������ȼ����������Ĵ���(DOR)��ʹ��ѡ��ǰָ������������Ȼ��
// ����ִ�����̶�д���亯��transfer()��
405 static void floppy_on_interrupt(void) // floppy_on() interrupt��
406 {
407 /* We cannot do a floppy-select, as that might sleep. We just force it */
/* ���Dz�����������ѡ�����������Ϊ����ܻ��������˯�ߡ�����ֻ����ʹ���Լ�ѡ�� */
// �����ǰ������������������Ĵ���DOR�еIJ�ͬ������Ҫ��������DORΪ��ǰ��������
// ������������Ĵ��������ǰDOR�Ժ�ʹ�ö�ʱ���ӳ�2���δ�ʱ�䣬��������õ�ִ
// �С�Ȼ��������̶�д���亯��transfer()������ǰ��������DOR�е��������ô�Ϳ���
// ֱ�ӵ������̶�д���亯����
408 selected = 1; // ����ѡ����ǰ��������־��
409 if (current_drive != (current_DOR & 3)) {
410 current_DOR &= 0xFC;
411 current_DOR |= current_drive;
412 outb(current_DOR,FD_DOR); // ����������Ĵ��������ǰDOR��
413 add_timer(2,&transfer); // ���Ӷ�ʱ����ִ�д��亯����
414 } else
415 transfer(); // ִ�����̶�д���亯����
416 }
417
//// ���̶�д�������������
// �ú�����������������������Ҫ�ĺ�������Ҫ�����ǣ��ٴ����и�λ��־������У����־��
// λ������������������е��豸�ż���ȡ��������ָ�������IJ����飻�������ںӶ�ʱ����
// �����̶�/д������
418 void do_fd_request(void)
419 {
420 unsigned int block;
421
// ���ȼ���Ƿ��и�λ��־������У����־��λ������������ִ����ر�־�Ĵ�������
// ��ͷ��ء������λ��־����λ����ִ�����̸�λ���������ء��������У����־����λ��
// ��ִ����������У�����������ء�
422 seek = 0; // ��Ѱ����־��
423 if (reset) { // ��λ��־����λ��
424 reset_floppy();
425 return;
426 }
427 if (recalibrate) { // ����У����־����λ��
428 recalibrate_floppy();
429 return;
430 }
// ���������������ܴ����↑ʼ����������blk.h�ļ��е�INIT_REQUEST��������������
// �Ϸ��ԣ������û�����������˳����μ�blk.h,127����Ȼ�������������е��豸��ȡ����
// ����ָ�������IJ����顣��������齫�����������������̲���ʹ�õ�ȫ�ֱ��������飨��
// ��112 - 122�У����������豸���е��������� (MINOR(CURRENT->dev)>>2) ������������
// ������floppy_type[]������ֵ��ȡ��ָ�������IJ����顣
431 INIT_REQUEST;
432 floppy = (MINOR(CURRENT->dev)>>2) + floppy_type;
// ���濪ʼ����112--122���ϵ�ȫ�ֱ���ֵ�������ǰ��������current_drive����������
// ��ָ�����������ţ����ñ�־seek����ʾ��ִ�ж�/д����֮ǰ��Ҫ����������ִ��Ѱ����
// ����Ȼ��ѵ�ǰ������������Ϊ��������ָ�����������š�
433 if (current_drive != CURRENT_DEV) // CURRENT_DEV����������ָ���������š�
434 seek = 1;
435 current_drive = CURRENT_DEV;
// ���ö�д��ʼ����block����Ϊÿ�ζ�д���Կ�Ϊ��λ��1��Ϊ2����������������ʼ����
// ��Ҫ����ȴ�����������С2������������˵����������������Ч�������ô�����������
// ȥִ����һ�������
436 block = CURRENT->sector; // ȡ��ǰ��������������ʼ�����š�
437 if (block+2 > floppy->size) { // ���block + 2���ڴ�������������
438 end_request(0); // ������������������
439 goto repeat;
440 }
// �����Ӧ�ڴŵ��ϵ������š���ͷ�š��ŵ��š���Ѱ�ŵ��ţ�������������ͬ��ʽ���̣���
441 sector = block % floppy->sect; // ��ʼ������ÿ�ŵ�������ȡģ���ôŵ��������š�
442 block /= floppy->sect; // ��ʼ������ÿ�ŵ�������ȡ��������ʼ�ŵ�����
443 head = block % floppy->head; // ��ʼ�ŵ����Դ�ͷ��ȡģ���ò����Ĵ�ͷ�š�
444 track = block / floppy->head; // ��ʼ�ŵ����Դ�ͷ��ȡ�����ò����Ĵŵ��š�
445 seek_track = track << floppy->stretch; // ��Ӧ�������������ͽ��е�������Ѱ���š�
// �ٿ����Ƿ���Ҫ����ִ��Ѱ�����������Ѱ�����뵱ǰ��ͷ���ڴŵ��Ų�ͬ������Ҫ����
// Ѱ����������������ҪѰ����־seek�������������ִ�е���������command��
446 if (seek_track != current_track)
447 seek = 1;
448 sector++; // ������ʵ�����������Ǵ�1����
449 if (CURRENT->cmd == READ) // ����������Ƕ����������ö������롣
450 command = FD_READ;
451 else if (CURRENT->cmd == WRITE) // �����������д����������д�����롣
452 command = FD_WRITE;
453 else
454 panic("do_fd_request: unknown command");
// ���������ú� 112--122��������ȫ�ֱ���ֵ֮�����ǿ��Կ�ʼִ������������ˡ��ò�
// �����ö�ʱ������������ΪΪ���ܶ��������ж�д��������Ҫ�����������������ﲢ�ﵽ��
// ����ת�ٶȡ�������Ҫһ����ʱ�䡣����������� ticks_to_floppy_on() ������������ʱ
// ʱ�䣬Ȼ��ʹ�ø���ʱ�趨һ����ʱ������ʱ�䵽ʱ�͵��ú���floppy_on_interrupt()��
455 add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
456 }
457
// ���������������̺��е����ݿ�������
458 static int floppy_sizes[] ={
459 0, 0, 0, 0,
460 360, 360 ,360, 360,
461 1200,1200,1200,1200,
462 360, 360, 360, 360,
463 720, 720, 720, 720,
464 360, 360, 360, 360,
465 720, 720, 720, 720,
466 1440,1440,1440,1440
467 };
468
//// ����ϵͳ��ʼ����
// �������̿��豸������Ĵ�������do_fd_request()�������������ж��ţ�int 0x26����Ӧ
// Ӳ���ж������ź�IRQ6���� Ȼ��ȡ���Ը��ж��źŵ����Σ����������̿�����FDC������
// �������źš��ж���������IDT�����������������ú�set_trap_gate()������ͷ�ļ�
// include/asm/system.h�С�
469 void floppy_init(void)
470 {
// ���������ж�����������floppy_interrupt��kernel/sys_call.s��267�У������жϴ���
// ���̡��жϺ�Ϊint 0x26��38������Ӧ8259AоƬ�ж������ź�IRQ6��
471 blk_size[MAJOR_NR] = floppy_sizes;
472 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; // = do_fd_request()��
473 set_trap_gate(0x26,&floppy_interrupt); // ������������������
474 outb(inb_p(0x21)&~0x40,0x21); // ��λ�����ж���������λ��
475 }
476
1 /*
2 * linux/kernel/keyboard.S
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * Thanks to Alfred Leung for US keyboard patches
9 * Wolfgang Thiel for German keyboard patches
10 * Marc Corsini for the French keyboard
11 */
/*
* ��лAlfred Leung������US���̲�������
* Wolfgang Thiel�����˵�����̲�������
* Marc Corsini�����˷��ļ��̲�������
*/
12
13 /* KBD_FINNISH for Finnish keyboards
14 * KBD_US for US-type
15 * KBD_GR for German keyboards
16 * KBD_FR for Frech keyboard
17 */
/*
* KBD_FINNISH �Ƿ������̡�
* KBD_US ����ʽ���̡�
* KBD_GR �ǵ�ʽ���̡�
* KBD_FR �Ƿ�ʽ���̡�
*/
18 #define KBD_FINNISH // ����ʹ�õļ������͡����ں���ѡ����õ��ַ�ӳ�������
19
20 .text
21 .globl _keyboard_interrupt // ����Ϊȫ�ֱ����������ڳ�ʼ��ʱ���ü����ж���������
22
23 /*
24 * these are for the keyboard read functions
25 */
/*
* ������Щ���ڶ����̲�����
*/
// size�Ǽ��̻�������������У����ȣ��ֽ�������
/* ֵ������2�Ĵη���������tty_io.c�е�ֵƥ��!!!! */
26 size = 1024 /* must be a power of two ! And MUST be the same
27 as in tty_io.c !!!! */
// �����Ǽ��̻���������ݽṹtty_queue�е�ƫ������include/linux/tty.h����16�У���
28 head = 4 // ������ͷָ���ֶ���tty_queue�ṹ�е�ƫ�ơ�
29 tail = 8 // ������βָ���ֶ�ƫ�ơ�
30 proc_list = 12 // �ȴ��û�����еĽ����ֶ�ƫ�ơ�
31 buf = 16 // �������ֶ�ƫ�ơ�
32
// �ڱ�������ʹ����3����־�ֽڡ�mode�Ǽ����������ctrl��alt��caps���İ���״̬��־��
// leds �����ڱ�ʾ����ָʾ�Ƶ�״̬��־�� e0�ǵ��յ�ɨ���� 0xe0 �� 0xe1 ʱ���õı�־��
// ÿ���ֽڱ�־�и�λ�ĺ��������˵����
// (1) mode�Ǽ���������İ���״̬��־��
// ��ʾ��Сдת����(caps)��������(alt)�����Ƽ�(ctrl)�ͻ�����(shift)��״̬��
// λ7 caps�����£�
// λ6 caps����״̬��Ӧ����leds�ж�Ӧcaps�ı�־λһ������
// λ5 ��alt�����£�
// λ4 ��alt�����£�
// λ3 ��ctrl�����£�
// λ2 ��ctrl�����£�
// λ1 ��shift�����£�
// λ0 ��shift�����¡�
// (2) leds�����ڱ�ʾ����ָʾ�Ƶ�״̬��־������ʾ������������num-lock������Сдת��
// ����caps-lock��������������scroll-lock����LED�����״̬��
// λ7-3 ȫ0���ã�
// λ2 caps-lock��
// λ1 num-lock����ʼ��1��Ҳ����������������(num-lock)�����Ϊ������
// λ0 scroll-lock��
// (3) ��ɨ������0xe0��0xe1ʱ���øñ�־����ʾ�������1����2���ַ�ɨ���롣ͨ
// �����յ�ɨ����0xe0����ζ�Ż���һ���ַ�����������յ�ɨ����0xe1���ʾ���滹��
// ����2���ַ����μ������б���˵����
// λ1 =1 �յ�0xe1��־��
// λ0 =1 �յ�0xe0��־��
33 mode: .byte 0 /* caps, alt, ctrl and shift mode */
34 leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
35 e0: .byte 0
36
37 /*
38 * con_int is the real interrupt routine that reads the
39 * keyboard scan-code and converts it into the appropriate
40 * ascii character(s).
41 */
/*
* con_int��ʵ�ʵ��жϴ����ӳ������ڶ�����ɨ���벢����ת��
* ����Ӧ��ascii�ַ���[ ע�����Ӣ��ע���ѹ�ʱ��]
*/
//// �����жϴ���������ڵ㡣
// �����̿��������յ��û���һ����������ʱ���ͻ����жϿ���������һ�������ж������ź�
// IRQ1����CPU��Ӧ������ʱ�ͻ�ִ�м����жϴ��������жϴ��������Ӽ��̿�������
// Ӧ�˿ڣ�0x60�����밴��ɨ���룬�����ö�Ӧ��ɨ�����ӳ�����д�����
// ���ȴӶ˿�0x60��ȡ��ǰ������ɨ���롣Ȼ���жϸ�ɨ�����Ƿ���0xe0 �� 0xe1�������
// �Ļ������̶Լ��̿���������Ӧ�𣬲����жϿ����������жϽ�����EOI���źţ���������
// �̿������ܼ��������ж��źţ��Ӷ������������պ������ַ��� ������յ���ɨ���벻��
// ����������ɨ���룬���Ǿ���ɨ����ֵ���ð�����ת�� key_table ����Ӧ���������ӳ�
// ��ɨ�����Ӧ���ַ�������ַ��������read_q�С�Ȼ���ڶԼ��̿���������Ӧ��
// ������EOI�ź�֮���ú���do_tty_interrupt()��ʵ�����ǵ��� copy_to_cooked()��
// ��read_q�е��ַ�����������ŵ�secondary���������С�
42 _keyboard_interrupt:
43 pushl %eax
44 pushl %ebx
45 pushl %ecx
46 pushl %edx
47 push %ds
48 push %es
49 movl $0x10,%eax // ��ds��es�μĴ�����Ϊ�ں����ݶΡ�
50 mov %ax,%ds
51 mov %ax,%es
52 movl _blankinterval,%eax
53 movl %eax,_blankcount // Ԥ�ú���ʱ�����ֵΪblankinterval���δ�������
54 xorl %eax,%eax /* %eax is scan code */ /* eax����ɨ���� */
55 inb $0x60,%al // ��ȡɨ������al��
56 cmpb $0xe0,%al // ɨ������0xe0����������ת������e0��־���봦��
57 je set_e0
58 cmpb $0xe1,%al // ɨ������0xe1����������ת������e1��־���봦��
59 je set_e1
60 call key_table(,%eax,4) // ���ü��������� key_table + eax*4���μ�502�У���
61 movb $0,e0 // ����֮��λe0��־��
// ������δ��루55-65�У����ʹ��8255A��PC�����̵�·����Ӳ����λ�������˿�0x61
// ��8255A �����B �ĵ�ַ��������˿ڵĵ�7λ��PB7�����ڽ�ֹ�������Լ������ݵĴ�����
// ��γ������ڶ��յ���ɨ��������Ӧ�𡣷��������Ƚ�ֹ���̣�Ȼ�����������������̹�����
62 e0_e1: inb $0x61,%al // ȡPPI�˿�B״̬����λ7��������/��ֹ��0/1�����̡�
63 jmp 1f // �ӳ�һ�ᡣ
64 1: jmp 1f
65 1: orb $0x80,%al // alλ7��λ����ֹ���̹�������
66 jmp 1f
67 1: jmp 1f
68 1: outb %al,$0x61 // ʹPPI PB7λ��λ��
69 jmp 1f
70 1: jmp 1f
71 1: andb $0x7F,%al // alλ7��λ��
72 outb %al,$0x61 // ʹPPI PB7λ��λ���������̹�������
73 movb $0x20,%al // ��8259�ж�оƬ����EOI(�жϽ���)�źš�
74 outb %al,$0x20
75 pushl $0 // ����̨tty��=0����Ϊ������ջ��
76 call _do_tty_interrupt // ���յ�����ת���ɹ淶ģʽ������ڹ淶�ַ���������С�
77 addl $4,%esp // ������ջ�IJ��������������ļĴ��������жϷ��ء�
78 pop %es
79 pop %ds
80 popl %edx
81 popl %ecx
82 popl %ebx
83 popl %eax
84 iret
85 set_e0: movb $1,e0 // �յ�ɨ��ǰ����0xe0ʱ������e0��־��λ0����
86 jmp e0_e1
87 set_e1: movb $2,e0 // �յ�ɨ��ǰ����0xe1ʱ������e1��־��λ1����
88 jmp e0_e1
89
90 /*
91 * This routine fills the buffer with max 8 bytes, taken from
92 * %ebx:%eax. (%edx is high). The bytes are written in the
93 * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.
94 */
/*
* ������ӳ����ebx:eax�е����8���ַ����뻺������С���ebx��
* ���֣���д���ַ���˳����al,ah,eal,eah,bl,bh...ֱ��eax����0��
*/
// ���ȴӻ�����е�ַ��table_list��tty_io.c��99�У�ȡ����̨�Ķ��������read_q��ַ��
// Ȼ���al�Ĵ����е��ַ����Ƶ�������ͷָ�봦����ͷָ��ǰ��1�ֽ�λ�á���ͷָ���Ƴ�
// ����������ĩ�ˣ���������Ƶ���������ʼ���� Ȼ���ٿ�����ʱ��������Ƿ����������Ƚ�
// һ�¶���ͷָ���Ƿ���βָ����ȣ���ȱ�ʾ������ ����������Ͱ�ebx:eax�п��ܻ��е�
// �����ַ�ȫ���������������������δ�����Ͱ�ebx:eax��������������8�����أ�����ah
// ֵ�Ƶ�al��bl��ah��bh��bl����Ȼ���ظ������al�Ĵ������̡�ֱ�������ַ����������
// �ͱ��浱ǰͷָ��ֵ���ټ��һ���Ƿ��н��̵ȴ��Ŷ����У�����оȻ���֮��
95 put_queue:
96 pushl %ecx
97 pushl %edx // �¾�ȡ����̨tty�ṹ�ж��������ָ�롣
98 movl _table_list,%edx # read-queue for console
99 movl head(%edx),%ecx // ȡ����ͷָ����ecx��
100 1: movb %al,buf(%edx,%ecx) // ��al�е��ַ�����ͷָ��λ�ô���
101 incl %ecx // ͷָ��ǰ��1�ֽڡ�
102 andl $size-1,%ecx // ����ͷָ�롣������������ĩ�����ƻؿ�ʼ����
103 cmpl tail(%edx),%ecx # buffer full - discard everything
// ͷָ��==βָ���𣿣���������������𣿣�
104 je 3f // ��������������δ������ַ�ȫ������
105 shrdl $8,%ebx,%eax // ��ebx��8����������8λ��eax�У�ebx���䡣
106 je 2f // �����ַ�����û�У�����0������ת��
107 shrl $8,%ebx // ��ebxֵ����8λ������ת�����1����������
108 jmp 1b
109 2: movl %ecx,head(%edx) // ���ѽ������ַ���������У���ͷָ�롣
110 movl proc_list(%edx),%ecx // �ö��еĵȴ�����ָ�룿
111 testl %ecx,%ecx // ����Ƿ��еȴ��ö��еĽ��̡�
112 je 3f // �ޣ�����ת��
113 movl $0,(%ecx) // �У����ѽ��̣��øý���Ϊ����״̬����
114 3: popl %edx
115 popl %ecx
116 ret
117
// �����↑ʼ�Ǽ���ת��key_table��ָ���Ӧ�ĸ������������ɼ��������ӳ��������
// 53�������á�����ת��key_table�ڵ�513�п�ʼ��
//
// ������δ������ctrl��alt��ɨ���룬�ֱ�����ģʽ��־mode����Ӧλ������ڸ�ɨ��
// ��֮ǰ�յ���0xe0ɨ���루e0��־��λ������˵�����µ��Ǽ����ұߵ�ctrl��alt������
// ��Ӧ����ctrl��alt��ģʽ��־mode�еı���λ��
118 ctrl: movb $0x04,%al // 0x4��mode����ctrl����Ӧ�ı���λ��λ2����
119 jmp 1f
120 alt: movb $0x10,%al // 0x10��mode����alt����Ӧ�ı���λ��λ4����
121 1: cmpb $0,e0 // e0��λ���𣨰��µ����ұߵ�ctrl/alt���𣩣�
122 je 2f // ������ת��
123 addb %al,%al // �ǣ���ij�����Ӧ�Ҽ���־λ��λ3��λ5����
124 2: orb %al,mode // ����mode��־�ж�Ӧ�ı���λ��
125 ret
// ��δ��봦��ctrl��alt���ɿ�ʱ��ɨ���룬��λģʽ��־mode�еĶ�Ӧ����λ���ڴ���
// ʱҪ����e0��־�Ƿ���λ���ж��Ƿ��Ǽ����ұߵ�ctrl��alt����
126 unctrl: movb $0x04,%al // mode����ctrl����Ӧ�ı���λ��λ2����
127 jmp 1f
128 unalt: movb $0x10,%al // 0x10��mode����alt����Ӧ�ı���λ��λ4����
129 1: cmpb $0,e0 // e0��λ�����ͷŵ����ұߵ�ctrl/alt���𣩣�
130 je 2f // ���ǣ���ת��
131 addb %al,%al // �ǣ���ijɸ�λ��Ӧ�Ҽ��ı�־λ��λ3��λ5����
132 2: notb %al // ��λmode��־�ж�Ӧ�ı���λ��
133 andb %al,mode
134 ret
135
// ��δ��봦������shift�����º��ɿ�ʱ��ɨ���룬�ֱ����ú�λmode�е���Ӧλ��
136 lshift:
137 orb $0x01,mode // ����shift�����£�����mode��λ0��
138 ret
139 unlshift:
140 andb $0xfe,mode // ����shift���ɿ�����λmode��λ0��
141 ret
142 rshift:
143 orb $0x02,mode // ����shift�����£�����mode��λ1��
144 ret
145 unrshift:
146 andb $0xfd,mode // ����shift���ɿ�����λmode��λ1��
147 ret
148
// ��δ�����յ�caps��ɨ������д�����ͨ��mode��λ7����֪��caps����ǰ�Ƿ�������
// �ڰ���״̬�������أ�����ͷ�תmode��־��caps�����µı���λ��λ6����leds��
// ־��caps-lock����λ��λ2��������mode��־��caps���Ѱ��±�־λ��λ7����
149 caps: testb $0x80,mode // ����mode��λ7�Ƿ�����λ�����ڰ���״̬����
150 jne 1f // ����Ѵ��ڰ���״̬���أ�186�У���
151 xorb $4,leds // ��תleds��־��caps-lock����λ��λ2����
152 xorb $0x40,mode // ��תmode��־��caps�����µı���λ��λ6����
153 orb $0x80,mode // ����mode��־��caps���Ѱ��±�־λ��λ7����
// ��δ������leds��־��������ر�LEDָʾ����
154 set_leds:
155 call kb_wait // �ȴ����̿��������뻺��ա�
156 movb $0xed,%al /* set leds command */
157 outb %al,$0x60 // ���ͼ�������0xed��0x60�˿ڡ�
158 call kb_wait
159 movb leds,%al // ȡleds��־����Ϊ������
160 outb %al,$0x60 // ������
161 ret
162 uncaps: andb $0x7f,mode // caps���ɿ�����λmode�еĶ�Ӧλ��λ7����
163 ret
164 scroll:
165 testb $0x03,mode // ����ʱctrl��Ҳͬʱ���£���
166 je 1f
167 call _show_mem // ��ʾ�ڴ�״̬��Ϣ��mm/memory.c��457�У���
168 jmp 2f
169 1: call _show_state // ������ʾ����״̬��Ϣ��kernel/sched.c��45�У���
170 2: xorb $1,leds // scroll�����£���תleds�ж�Ӧλ��λ0����
171 jmp set_leds // ����leds��־���¿�����ر�LEDָʾ����
172 num: xorb $2,leds // num�����£���תleds�еĶ�Ӧλ��λ1����
173 jmp set_leds // ����leds��־���¿�����ر�LEDָʾ����
174
175 /*
176 * curosr-key/numeric keypad cursor keys are handled here.
177 * checking for numeric keypad etc.
178 */
/*
* ���ﴦ�������/����С���̷�������������С���̵ȡ�
*/
179 cursor:
180 subb $0x47,%al // ɨ���������ּ����ϵļ�����ɨ����>=0x47�������ģ�
181 jb 1f // ���С�����������أ�198�У���
182 cmpb $12,%al // ���ɨ���� > 0x53��0x53 - 0x47 = 12������
183 ja 1f // ��ʾɨ����ֵ����83��0x53���������������ء�
184 jne cur2 /* check for ctrl-alt-del */ /* ���ctrl-alt-del��*/
// ������12��˵��del���ѱ����£�������ж�ctrl��alt�Ƿ�Ҳ��ͬʱ���¡�
185 testb $0x0c,mode // ��ctrl�����������ޣ�����ת��
186 je cur2
187 testb $0x30,mode // ��alt��������
188 jne reboot // �У�����ת��������������594�У���
189 cur2: cmpb $0x01,e0 /* e0 forces cursor movement */ /* e0��λָ����ƶ�*/
// e0��־��λ����
190 je cur // ��λ�ˣ�����ת����ƶ�������cur��
191 testb $0x02,leds /* not num-lock forces cursor */ /* num-lock������*/
// ����leds�б�־num-lock����־�Ƿ���λ��
192 je cur // ��û����λ��num��LED����������Ҳ��������ƶ���
193 testb $0x03,mode /* shift forces cursor */ /* shift��Ҳʹ����ƶ� */
// ����ģʽ��־mode��shift���±�־��
194 jne cur // �����shift�����£���Ҳ���й���ƶ�������
195 xorl %ebx,%ebx // �����ѯС���ֱ���199�У���ȡ��������ASCII�롣
196 movb num_table(%eax),%al // ��eax��Ϊ����ֵ��ȡ��Ӧ�����ַ���al��
197 jmp put_queue // �ַ����뻺������С�����Ҫ������е��ַ���<=4�����
198 1: ret // ��ִ��put_queueǰ���ebx���㣬��87���ϵ�ע�͡�
199
// ��δ��봦������ƶ������ɾ��������
200 cur: movb cur_table(%eax),%al // ȡ����ַ�������Ӧ���Ĵ����ַ���al��
201 cmpb $'9,%al // ���ַ�<='9'��5��6��2��3����˵������һҳ����һҳ��
202 ja ok_cur // �����ɾ�����������ַ�������Ҫ�����ַ�'~'������
203 movb $'~,%ah // ���ں˲�û�ж����ǽ���ʶ��ʹ�����
204 ok_cur: shll $16,%eax // ��ax�������Ƶ�eax�����С�
205 movw $0x5b1b,%ax // ��'esc ['����ax����eax�������ַ�����ƶ����С�
206 xorl %ebx,%ebx // ����ֻ���eax���ַ�������У������Ҫ��ebx���㡣
207 jmp put_queue // �����ַ����뻺������С�
208
209 #if defined(KBD_FR)
210 num_table:
211 .ascii "789 456 1230." // ����С�����ϼ���Ӧ������ASCII�����
212 #else
213 num_table:
214 .ascii "789 456 1230,"
215 #endif
216 cur_table:
217 .ascii "HA5 DGC YB623" // С�����Ϸ���������ɾ������Ӧ���ƶ���ʾ�ַ�����
218
219 /*
220 * this routine handles function keys
221 */
/*
* �����ӳ��������ܼ���
*/
// �ѹ��ܼ�ɨ����任��ת���ַ����в���ŵ��������С�
222 func:
223 subb $0x3B,%al // ��'F1'��ɨ������0x3B�����al���ǹ��ܼ������š�
224 jb end_func // ���ɨ����С��0x3b�����������ء�
225 cmpb $9,%al // ���ܼ���F1--F10��
226 jbe ok_func // �ǣ�����ת��
227 subb $18,%al // �ǹ��ܼ�F11��F12��F11��F12ɨ������0x57��0x58��
228 cmpb $10,%al // �ǹ��ܼ�F11��
229 jb end_func // ���ǣ����������ء�
230 cmpb $11,%al // �ǹ��ܼ�F12��
231 ja end_func // ���ǣ����������ء�
232 ok_func:
233 testb $0x10,mode // ��alt��Ҳͬʱ��������
234 jne alt_func // ������ת����������������նˡ�
235 cmpl $4,%ecx /* check that there is enough room */ /*���ռ�*/
236 jl end_func // [??]��Ҫ����4���ַ�������Ų��£��ء�
237 movl func_table(,%eax,4),%eax // ȡ���ܼ���Ӧ�ַ����С�
238 xorl %ebx,%ebx // ��Ҫ��������ַ���=4�����ִ��put_queue֮ǰ
239 jmp put_queue // ���ebx���㡣
// ���� alt + Fn ��ϼ����ı���������նˡ���ʱeax���ǹ��ܼ������ţ�F1 -- 0������Ӧ
// ��������ն˺š�
240 alt_func:
241 pushl %eax // ��������ն˺���ջ����Ϊ������
242 call _change_console // ���ĵ�ǰ��������նˣ�chr_dev/tty_io.c��87�У���
243 popl %eax // ����������
244 end_func:
245 ret
246
247 /*
248 * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.
249 */
/*
* ���ܼ����͵�ɨ���룬F1��Ϊ��'esc [ [ A'�� F2��Ϊ��'esc [ [ B'�ȡ�
*/
250 func_table:
251 .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b
252 .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b
253 .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b
254
// ɨ����-ASCII�ַ�ӳ�����
// ����ǰ�涨��ļ�������(FINNISH��US��GERMEN��FRANCH)������Ӧ����ɨ����ӳ�䵽
// ASCII�ַ���
255 #if defined(KBD_FINNISH) // �����Ƿ�������̵�ɨ����ӳ�����
256 key_map:
257 .byte 0,27 // ɨ����0x00,0x01��Ӧ��ASCII�룻
258 .ascii "1234567890+'" // ɨ����0x02,...0x0c,0x0d��Ӧ��ASCII�룬�������ơ�
259 .byte 127,9
260 .ascii "qwertyuiop}"
261 .byte 0,13,0
262 .ascii "asdfghjkl|{"
263 .byte 0,0
264 .ascii "'zxcvbnm,.-"
265 .byte 0,'*,0,32 /* 36-39 */ /* ɨ����0x36-0x39��Ӧ��ASCII�� */
266 .fill 16,1,0 /* 3A-49 */ /* ɨ����0x3A-0x49��Ӧ��ASCII�� */
267 .byte '-,0,0,0,'+ /* 4A-4E */ /* ɨ����0x4A-0x4E��Ӧ��ASCII�� */
268 .byte 0,0,0,0,0,0,0 /* 4F-55 */ /* ɨ����0x4F-0x55��Ӧ��ASCII�� */
269 .byte '<
270 .fill 10,1,0
271
272 shift_map: // shift��ͬʱ����ʱ��ӳ�����
273 .byte 0,27
274 .ascii "!\"#$%&/()=?`"
275 .byte 127,9
276 .ascii "QWERTYUIOP]^"
277 .byte 13,0
278 .ascii "ASDFGHJKL\\["
279 .byte 0,0
280 .ascii "*ZXCVBNM;:_"
281 .byte 0,'*,0,32 /* 36-39 */
282 .fill 16,1,0 /* 3A-49 */
283 .byte '-,0,0,0,'+ /* 4A-4E */
284 .byte 0,0,0,0,0,0,0 /* 4F-55 */
285 .byte '>
286 .fill 10,1,0
287
288 alt_map: // alt��ͬʱ����ʱ��ӳ�����
289 .byte 0,0
290 .ascii "\0@\0$\0\0{[]}\\\0"
291 .byte 0,0
292 .byte 0,0,0,0,0,0,0,0,0,0,0
293 .byte '~,13,0
294 .byte 0,0,0,0,0,0,0,0,0,0,0
295 .byte 0,0
296 .byte 0,0,0,0,0,0,0,0,0,0,0
297 .byte 0,0,0,0 /* 36-39 */
298 .fill 16,1,0 /* 3A-49 */
299 .byte 0,0,0,0,0 /* 4A-4E */
300 .byte 0,0,0,0,0,0,0 /* 4F-55 */
301 .byte '|
302 .fill 10,1,0
303
304 #elif defined(KBD_US) // ��������ʽ���̵�ɨ����ӳ�����
305
306 key_map:
307 .byte 0,27
308 .ascii "1234567890-="
309 .byte 127,9
310 .ascii "qwertyuiop[]"
311 .byte 13,0
312 .ascii "asdfghjkl;'"
313 .byte '`,0
314 .ascii "\\zxcvbnm,./"
315 .byte 0,'*,0,32 /* 36-39 */
316 .fill 16,1,0 /* 3A-49 */
317 .byte '-,0,0,0,'+ /* 4A-4E */
318 .byte 0,0,0,0,0,0,0 /* 4F-55 */
319 .byte '<
320 .fill 10,1,0
321
322
323 shift_map:
324 .byte 0,27
325 .ascii "!@#$%^&*()_+"
326 .byte 127,9
327 .ascii "QWERTYUIOP{}"
328 .byte 13,0
329 .ascii "ASDFGHJKL:\""
330 .byte '~,0
331 .ascii "|ZXCVBNM<>?"
332 .byte 0,'*,0,32 /* 36-39 */
333 .fill 16,1,0 /* 3A-49 */
334 .byte '-,0,0,0,'+ /* 4A-4E */
335 .byte 0,0,0,0,0,0,0 /* 4F-55 */
336 .byte '>
337 .fill 10,1,0
338
339 alt_map:
340 .byte 0,0
341 .ascii "\0@\0$\0\0{[]}\\\0"
342 .byte 0,0
343 .byte 0,0,0,0,0,0,0,0,0,0,0
344 .byte '~,13,0
345 .byte 0,0,0,0,0,0,0,0,0,0,0
346 .byte 0,0
347 .byte 0,0,0,0,0,0,0,0,0,0,0
348 .byte 0,0,0,0 /* 36-39 */
349 .fill 16,1,0 /* 3A-49 */
350 .byte 0,0,0,0,0 /* 4A-4E */
351 .byte 0,0,0,0,0,0,0 /* 4F-55 */
352 .byte '|
353 .fill 10,1,0
354
355 #elif defined(KBD_GR) // �����ǵ�����̵�ɨ����ӳ�����
356
357 key_map:
358 .byte 0,27
359 .ascii "1234567890\\'"
360 .byte 127,9
361 .ascii "qwertzuiop@+"
362 .byte 13,0
363 .ascii "asdfghjkl[]^"
364 .byte 0,'#
365 .ascii "yxcvbnm,.-"
366 .byte 0,'*,0,32 /* 36-39 */
367 .fill 16,1,0 /* 3A-49 */
368 .byte '-,0,0,0,'+ /* 4A-4E */
369 .byte 0,0,0,0,0,0,0 /* 4F-55 */
370 .byte '<
371 .fill 10,1,0
372
373
374 shift_map:
375 .byte 0,27
376 .ascii "!\"#$%&/()=?`"
377 .byte 127,9
378 .ascii "QWERTZUIOP\\*"
379 .byte 13,0
380 .ascii "ASDFGHJKL{}~"
381 .byte 0,''
382 .ascii "YXCVBNM;:_"
383 .byte 0,'*,0,32 /* 36-39 */
384 .fill 16,1,0 /* 3A-49 */
385 .byte '-,0,0,0,'+ /* 4A-4E */
386 .byte 0,0,0,0,0,0,0 /* 4F-55 */
387 .byte '>
388 .fill 10,1,0
389
390 alt_map:
391 .byte 0,0
392 .ascii "\0@\0$\0\0{[]}\\\0"
393 .byte 0,0
394 .byte '@,0,0,0,0,0,0,0,0,0,0
395 .byte '~,13,0
396 .byte 0,0,0,0,0,0,0,0,0,0,0
397 .byte 0,0
398 .byte 0,0,0,0,0,0,0,0,0,0,0
399 .byte 0,0,0,0 /* 36-39 */
400 .fill 16,1,0 /* 3A-49 */
401 .byte 0,0,0,0,0 /* 4A-4E */
402 .byte 0,0,0,0,0,0,0 /* 4F-55 */
403 .byte '|
404 .fill 10,1,0
405
406
407 #elif defined(KBD_FR) // �����Ƿ�����̵�ɨ����ӳ�����
408
409 key_map:
410 .byte 0,27
411 .ascii "&{\"'(-}_/@)="
412 .byte 127,9
413 .ascii "azertyuiop^$"
414 .byte 13,0
415 .ascii "qsdfghjklm|"
416 .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */
417 .ascii "wxcvbn,;:!"
418 .byte 0,'*,0,32 /* 36-39 */
419 .fill 16,1,0 /* 3A-49 */
420 .byte '-,0,0,0,'+ /* 4A-4E */
421 .byte 0,0,0,0,0,0,0 /* 4F-55 */
422 .byte '<
423 .fill 10,1,0
424
425 shift_map:
426 .byte 0,27
427 .ascii "1234567890]+"
428 .byte 127,9
429 .ascii "AZERTYUIOP<>"
430 .byte 13,0
431 .ascii "QSDFGHJKLM%"
432 .byte '~,0,'#
433 .ascii "WXCVBN?./\\"
434 .byte 0,'*,0,32 /* 36-39 */
435 .fill 16,1,0 /* 3A-49 */
436 .byte '-,0,0,0,'+ /* 4A-4E */
437 .byte 0,0,0,0,0,0,0 /* 4F-55 */
438 .byte '>
439 .fill 10,1,0
440
441 alt_map:
442 .byte 0,0
443 .ascii "\0~#{[|`\\^@]}"
444 .byte 0,0
445 .byte '@,0,0,0,0,0,0,0,0,0,0
446 .byte '~,13,0
447 .byte 0,0,0,0,0,0,0,0,0,0,0
448 .byte 0,0
449 .byte 0,0,0,0,0,0,0,0,0,0,0
450 .byte 0,0,0,0 /* 36-39 */
451 .fill 16,1,0 /* 3A-49 */
452 .byte 0,0,0,0,0 /* 4A-4E */
453 .byte 0,0,0,0,0,0,0 /* 4F-55 */
454 .byte '|
455 .fill 10,1,0
456
457 #else
458 #error "KBD-type not defined"
459 #endif
460 /*
461 * do_self handles "normal" keys, ie keys that don't change meaning
462 * and which have just one character returns.
463 */
/*
* do_self���ڴ�������ͨ������Ҳ������û�б仯����ֻ��һ���ַ����صļ���
*/
// ���ȸ���mode��־ѡ��alt_map��shift_map��key_mapӳ���֮һ��
464 do_self:
465 lea alt_map,%ebx // ȡalt��ͬʱ����ʱ��ӳ�����ַalt_map��
466 testb $0x20,mode /* alt-gr */ /* ��alt��ͬʱ������? */
467 jne 1f // �ǣ�����ǰ��ת�����1����
468 lea shift_map,%ebx // ȡshift��ͬʱ����ʱ��ӳ�����ַshift_map��
469 testb $0x03,mode // ��shift��ͬʱ��������
470 jne 1f // �У�����ǰ��ת�����1��ȥӳ���ַ���
471 lea key_map,%ebx // ����ʹ����ͨӳ���key_map��
// Ȼ�����ɨ����ȡӳ����ж�Ӧ��ASCII�ַ�����û�ж�Ӧ�ַ����أ�תnone����
472 1: movb (%ebx,%eax),%al // ��ɨ������Ϊ����ֵ��ȡ��Ӧ��ASCII����al��
473 orb %al,%al // ��⿴�Ƿ��ж�Ӧ��ASCII�롣
474 je none // ��û��(��Ӧ��ASCII��=0)���ء�
// ��ctrl���Ѱ��»�caps�������������ַ��� 'a'--'}'��0x61--0x7D����Χ�ڣ�����ת��
// ��д�ַ���0x41--0x5D����
475 testb $0x4c,mode /* ctrl or caps */ /* ���Ƽ��Ѱ��»�caps����*/
476 je 2f // û�У�����ǰ��ת���2����
477 cmpb $'a,%al // ��al�е��ַ���'a'�Ƚϡ�
478 jb 2f // ��alֵ<'a'����ת���2����
479 cmpb $'},%al // ��al�е��ַ���'}'�Ƚϡ�
480 ja 2f // ��alֵ>'}'����ת���2����
481 subb $32,%al // ��alת��Ϊ��д�ַ�����0x20����
// ��ctrl���Ѱ��£������ַ��� '`'--'_'��0x40--0x5F��֮�䣬���Ǵ�д�ַ�������ת��Ϊ
// �����ַ���0x00--0x1F����
482 2: testb $0x0c,mode /* ctrl */ /* ctrl��ͬʱ��������*/
483 je 3f // ��û����ת���3��
484 cmpb $64,%al // ��al��'@'��64���ַ��Ƚϣ����ж��ַ�������Χ��
485 jb 3f // ��ֵ<'@'����ת���3��
486 cmpb $64+32,%al // ��al��'`'��96���ַ��Ƚϣ����ж��ַ�������Χ��
487 jae 3f // ��ֵ>='`'����ת���3��
488 subb $64,%al // ����al��0x40��ת��Ϊ0x00--0x1f�Ŀ����ַ���
// ����alt��ͬʱ���£����ַ���λ7��λ������ʱ����ֵ����0x7f����չ�ַ����е��ַ���
489 3: testb $0x10,mode /* left alt */ /* ��alt��ͬʱ���£�*/
490 je 4f // û�У���ת���4��
491 orb $0x80,%al // �ַ���λ7��λ��
// ��al�е��ַ��������������С�
492 4: andl $0xff,%eax // ��eax�ĸ��ֺ�ah��
493 xorl %ebx,%ebx // ���ڷ�������ַ���<=4��������ebx���㡣
494 call put_queue // ���ַ����뻺������С�
495 none: ret
496
497 /*
498 * minus has a routine of it's own, as a 'E0h' before
499 * the scan code for minus means that the numeric keypad
500 * slash was pushed.
501 */
/*
* ���������Լ��Ĵ����ӳ�����Ϊ�ڼ���ɨ����֮ǰ��0xe0
* ��ζ�Ű���������С�����ϵ�б�ܼ���
*/
// ע�⣬���ڷ�����͵�����̣�ɨ����0x35��Ӧ����'-'�����μ���264��365�С�
502 minus: cmpb $1,e0 // e0��־��λ����
503 jne do_self // û�У������do_self�Լ��ŷ�������ͨ������
504 movl $'/,%eax // ������'/'�滻����'-'��al��
505 xorl %ebx,%ebx // ���ڷ�������ַ���<=4��������ebx���㡣
506 jmp put_queue // �����ַ����뻺������С�
507
508 /*
509 * This table decides which routine to call when a scan-code has been
510 * gotten. Most routines just call do_self, or none, depending if
511 * they are make or break.
512 */
/*
* ������һ���ӳ����ַ��ת������ȡ��ɨ�������ݴ˱�������Ӧ��ɨ����
* �����ӳ���������õ��ӳ�����do_self��������none����������ǰ���
* ��make�������ͷż�(break)��
*/
513 key_table:
514 .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */
515 .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */
516 .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */
517 .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */
518 .long do_self,do_self,do_self,do_self /* 10-13 q w e r */
519 .long do_self,do_self,do_self,do_self /* 14-17 t y u i */
520 .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */
521 .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */
522 .long do_self,do_self,do_self,do_self /* 20-23 d f g h */
523 .long do_self,do_self,do_self,do_self /* 24-27 j k l | */
524 .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */
525 .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */
526 .long do_self,do_self,do_self,do_self /* 30-33 b n m , */
527 .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */
528 .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */
529 .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */
530 .long func,func,func,func /* 40-43 f6 f7 f8 f9 */
531 .long func,num,scroll,cursor /* 44-47 f10 num scr home */
532 .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */
533 .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */
534 .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */
535 .long none,none,do_self,func /* 54-57 sysreq ? < f11 */
536 .long func,none,none,none /* 58-5B f12 ? ? ? */
537 .long none,none,none,none /* 5C-5F ? ? ? ? */
538 .long none,none,none,none /* 60-63 ? ? ? ? */
539 .long none,none,none,none /* 64-67 ? ? ? ? */
540 .long none,none,none,none /* 68-6B ? ? ? ? */
541 .long none,none,none,none /* 6C-6F ? ? ? ? */
542 .long none,none,none,none /* 70-73 ? ? ? ? */
543 .long none,none,none,none /* 74-77 ? ? ? ? */
544 .long none,none,none,none /* 78-7B ? ? ? ? */
545 .long none,none,none,none /* 7C-7F ? ? ? ? */
546 .long none,none,none,none /* 80-83 ? br br br */
547 .long none,none,none,none /* 84-87 br br br br */
548 .long none,none,none,none /* 88-8B br br br br */
549 .long none,none,none,none /* 8C-8F br br br br */
550 .long none,none,none,none /* 90-93 br br br br */
551 .long none,none,none,none /* 94-97 br br br br */
552 .long none,none,none,none /* 98-9B br br br br */
553 .long none,unctrl,none,none /* 9C-9F br unctrl br br */
554 .long none,none,none,none /* A0-A3 br br br br */
555 .long none,none,none,none /* A4-A7 br br br br */
556 .long none,none,unlshift,none /* A8-AB br br unlshift br */
557 .long none,none,none,none /* AC-AF br br br br */
558 .long none,none,none,none /* B0-B3 br br br br */
559 .long none,none,unrshift,none /* B4-B7 br br unrshift br */
560 .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */
561 .long none,none,none,none /* BC-BF br br br br */
562 .long none,none,none,none /* C0-C3 br br br br */
563 .long none,none,none,none /* C4-C7 br br br br */
564 .long none,none,none,none /* C8-CB br br br br */
565 .long none,none,none,none /* CC-CF br br br br */
566 .long none,none,none,none /* D0-D3 br br br br */
567 .long none,none,none,none /* D4-D7 br br br br */
568 .long none,none,none,none /* D8-DB br ? ? ? */
569 .long none,none,none,none /* DC-DF ? ? ? ? */
570 .long none,none,none,none /* E0-E3 e0 e1 ? ? */
571 .long none,none,none,none /* E4-E7 ? ? ? ? */
572 .long none,none,none,none /* E8-EB ? ? ? ? */
573 .long none,none,none,none /* EC-EF ? ? ? ? */
574 .long none,none,none,none /* F0-F3 ? ? ? ? */
575 .long none,none,none,none /* F4-F7 ? ? ? ? */
576 .long none,none,none,none /* F8-FB ? ? ? ? */
577 .long none,none,none,none /* FC-FF ? ? ? ? */
578
579 /*
580 * kb_wait waits for the keyboard controller buffer to empty.
581 * there is no timeout - if the buffer doesn't empty, we hang.
582 */
/*
* �ӳ���kb_wait���ڵȴ����̿���������ա������ڳ�ʱ���� - ���
* ������Զ���յĻ�������ͻ���Զ�ȴ�(����)��
*/
583 kb_wait:
584 pushl %eax
585 1: inb $0x64,%al // �����̿�����״̬��
586 testb $0x02,%al // �������뻺�����Ƿ�Ϊ�գ�����0����
587 jne 1b // �����գ�����תѭ���ȴ���
588 popl %eax
589 ret
590 /*
591 * This routine reboots the machine by asking the keyboard
592 * controller to pulse the reset-line low.
593 */
/*
* ���ӳ���ͨ�����ü��̿���������λ����������壬ʹϵͳ��
* �����reboot����
*/
// ���ӳ����������ڴ��ַ0x472��дֵ0x1234����λ��������ģʽ��reboot_mode����־�֡�
// ������������ROM BIOS���ȡ������ģʽ��־ֵ��������ֵ��ָ����һ����ִ�С� �����
// ֵ��0x1234����BIOS �ͻ������ڴ�����̶�ִ����������Warm-boot�����̡� �������
// ֵΪ0����ִ����������Cold-boot�����̡�
594 reboot:
595 call kb_wait // ���ȵȴ����̿��������뻺�����ա�
596 movw $0x1234,0x472 /* don't do memory check */ /* ������ڴ� */
597 movb $0xfc,%al /* pulse reset and A20 low */
598 outb %al,$0x64 // ��ϵͳ��λ���ź�A20����������塣
599 die: jmp die // ͣ����
1 /*
2 * linux/kernel/console.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * console.c
9 *
10 * This module implements the console io functions
11 * 'void con_init(void)'
12 * 'void con_write(struct tty_queue * queue)'
13 * Hopefully this will be a rather complete VT102 implementation.
14 *
15 * Beeping thanks to John T Kohl.
16 *
17 * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
18 * Chars, and VT100 enhancements by Peter MacDonald.
19 */
/*
* console.c
*
* ��ģ��ʵ�ֿ���̨�����������
* 'void con_init(void)'
* 'void con_write(struct tty_queue * queue)'
* ϣ������һ���dz�������VT102ʵ�֡�
*
* ��лJohn T Kohl ʵ���˷���ָʾ�ӳ���
*
* �������̨����Ļ������������Ļ��������ɫ������ͼ���ַ���ʾ�Լ�
* VT100�ն���ǿ������Peter MacDonald���ơ�
*/
20
21 /*
22 * NOTE!!! We sometimes disable and enable interrupts for a short while
23 * (to put a word in video IO), but this will work even for keyboard
24 * interrupts. We know interrupts aren't enabled when getting a keyboard
25 * interrupt, as we use trap-gates. Hopefully all is well.
26 */
/*
* ע��!!! ������ʱ���ݵؽ�ֹ�������жϣ������һ����(word) ����ƵIO������
* ��ʹ���ڼ����ж���Ҳ�ǿ��Թ����ġ���Ϊ����ʹ�������ţ���������֪���ڴ���
* һ�������жϹ����ڼ��ж��DZ���ֹ�ġ�ϣ��һ�о�������
*/
27
28 /*
29 * Code to check for different video-cards mostly by Galen Hunt,
30 * <g-hunt@ee.utah.edu>
31 */
/*
* ��ⲻͬ��ʾ���Ĵ����������Galen Hunt��д�ģ�
* <g-hunt@ee.utah.edu>
*/
32
33 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
34 #include <linux/tty.h> // ttyͷ�ļ��������й�tty_io������ͨ�ŷ���IJ�����������
35 #include <linux/config.h> // �ں�����ͷ�ļ�������Ӳ�����ͣ�HD_TYPE����ѡ�
36 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
37
38 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
39 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵȵĻ��ꡣ
40 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
41
42 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
43 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
44
// �÷��ų��������ն�IO�ṹ��Ĭ�����ݡ����з��ų��������include/termios.h�ļ���
45 #define DEF_TERMIOS \
46 (struct termios) { \
47 ICRNL, \
48 OPOST | ONLCR, \
49 0, \
50 IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, \
51 0, \
52 INIT_C_CC \
53 }
54
55
56 /*
57 * These are set up by the setup-routine at boot-time:
58 */
/*
* ��Щ��setup��������������ϵͳʱ���õIJ�����
*/
// �μ���boot/setup.s��ע�ͺ�setup�����ȡ��������ϵͳ��������
59
60 #define ORIG_X (*(unsigned char *)0x90000) // ��ʼ����кš�
61 #define ORIG_Y (*(unsigned char *)0x90001) // ��ʼ����кš�
62 #define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) // ��ʼ��ʾҳ�档
63 #define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) // ��ʾģʽ��
64 #define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) // ��������
65 #define ORIG_VIDEO_LINES ((*(unsigned short *)0x9000e) & 0xff) // ��������
66 #define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) // [??]
67 #define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) // ��ʾ�ڴ��С��ɫ��ģʽ��
68 #define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) // ��ʾ�����Բ�����
69
// ������ʾ����ɫ/��ɫ��ʾģʽ���ͷ��ų�����
70 #define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ /* ��ɫ�ı� */
71 #define VIDEO_TYPE_CGA 0x11 /* CGA Display */ /* CGA��ʾ�� */
72 #define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ /* EGA/VGA��ɫ*/
73 #define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */ /* EGA/VGA��ɫ*/
74
75 #define NPAR 16 // ת���ַ�������������������
76
77 int NR_CONSOLES = 0; // ϵͳʵ��֧�ֵ��������̨������
78
79 extern void keyboard_interrupt(void); // �����жϴ�������keyboard.S����
80
// ������Щ��̬�����DZ��ļ�������ʹ�õ�һЩȫ�ֱ�����
// video_type; ʹ�õ���ʾ���ͣ�
// video_num_columns; ��Ļ�ı�������
// video_mem_base; ������ʾ�ڴ����ַ��
// video_mem_term; ������ʾ�ڴ�ĩ�˵�ַ��
// video_size_row; ��Ļÿ��ʹ�õ��ֽ�����
// video_num_lines; ��Ļ�ı�������
// video_page; ������ʾҳ�棻
// video_port_reg; ��ʾ����ѡ��Ĵ����˿ڣ�
// video_port_val; ��ʾ�������ݼĴ����˿ڡ�
81 static unsigned char video_type; /* Type of display being used */
82 static unsigned long video_num_columns; /* Number of text columns */
83 static unsigned long video_mem_base; /* Base of video memory */
84 static unsigned long video_mem_term; /* End of video memory */
85 static unsigned long video_size_row; /* Bytes per row */
86 static unsigned long video_num_lines; /* Number of test lines */
87 static unsigned char video_page; /* Initial video page */
88 static unsigned short video_port_reg; /* Video register select port */
89 static unsigned short video_port_val; /* Video register value port */
90 static int can_do_colour = 0; // ��־����ʹ�ò�ɫ���ܡ�
91
// �������̨�ṹ�����а���һ���������̨�ĵ�ǰ������Ϣ������vc_origin��vc_scr_end
// �ǵ�ǰ���ڴ������������ִ̨�п��ٹ�������ʱʹ�õ���ʼ�к�ĩ�ж�Ӧ����ʾ�ڴ�λ�á�
// vc_video_mem_start��vc_video_mem_end�ǵ�ǰ�������̨ʹ�õ���ʾ�ڴ����֡�
// vc -- Virtual Console��
92 static struct {
93 unsigned short vc_video_erase_char; // �����ַ����Լ��ַ���0x0720��
94 unsigned char vc_attr; // �ַ����ԡ�
95 unsigned char vc_def_attr; // Ĭ���ַ����ԡ�
96 int vc_bold_attr; // �����ַ����ԡ�
97 unsigned long vc_ques; // �ʺ��ַ���
98 unsigned long vc_state; // ����ת���������еĵ�ǰ״̬��
99 unsigned long vc_restate; // ����ת���������е���һ״̬��
100 unsigned long vc_checkin;
101 unsigned long vc_origin; /* Used for EGA/VGA fast scroll */
102 unsigned long vc_scr_end; /* Used for EGA/VGA fast scroll */
103 unsigned long vc_pos; // ��ǰ����Ӧ����ʾ�ڴ�λ�á�
104 unsigned long vc_x,vc_y; // ��ǰ����С���ֵ��
105 unsigned long vc_top,vc_bottom; // ����ʱ�����кţ������кš�
106 unsigned long vc_npar,vc_par[NPAR]; // ת�����в��������Ͳ������顣
107 unsigned long vc_video_mem_start; /* Start of video RAM */
108 unsigned long vc_video_mem_end; /* End of video RAM (sort of) */
109 unsigned int vc_saved_x; // ����Ĺ���кš�
110 unsigned int vc_saved_y; // ����Ĺ���кš�
111 unsigned int vc_iscolor; // ��ɫ��ʾ��־��
112 char * vc_translate; // ʹ�õ��ַ�����
113 } vc_cons [MAX_CONSOLES];
114
// Ϊ�˱������ã����¶��嵱ǰ���ڴ�������̨��Ϣ�ķ��š�����ͬ�ϡ�����currcons��ʹ��
// vc_cons[]�ṹ�ĺ��������еĵ�ǰ�����ն˺š�
115 #define origin (vc_cons[currcons].vc_origin) // ���ٹ���������ʼ�ڴ�λ�á�
116 #define scr_end (vc_cons[currcons].vc_scr_end) // ���ٹ�������ĩ���ڴ�λ�á�
117 #define pos (vc_cons[currcons].vc_pos)
118 #define top (vc_cons[currcons].vc_top)
119 #define bottom (vc_cons[currcons].vc_bottom)
120 #define x (vc_cons[currcons].vc_x)
121 #define y (vc_cons[currcons].vc_y)
122 #define state (vc_cons[currcons].vc_state)
123 #define restate (vc_cons[currcons].vc_restate)
124 #define checkin (vc_cons[currcons].vc_checkin)
125 #define npar (vc_cons[currcons].vc_npar)
126 #define par (vc_cons[currcons].vc_par)
127 #define ques (vc_cons[currcons].vc_ques)
128 #define attr (vc_cons[currcons].vc_attr)
129 #define saved_x (vc_cons[currcons].vc_saved_x)
130 #define saved_y (vc_cons[currcons].vc_saved_y)
131 #define translate (vc_cons[currcons].vc_translate)
132 #define video_mem_start (vc_cons[currcons].vc_video_mem_start) // ʹ���Դ����ʼλ�á�
133 #define video_mem_end (vc_cons[currcons].vc_video_mem_end) // ʹ���Դ��ĩ��λ�á�
134 #define def_attr (vc_cons[currcons].vc_def_attr)
135 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)
136 #define iscolor (vc_cons[currcons].vc_iscolor)
137
138 int blankinterval = 0; // �趨����Ļ�������ʱ�䡣
139 int blankcount = 0; // ����ʱ�������
140
141 static void sysbeep(void); // ϵͳ����������
142
143 /*
144 * this is what the terminal answers to a ESC-Z or csi0c
145 * query (= vt100 response).
146 */
/*
* �������ն˻�ӦESC-Z��csi0c�����Ӧ��=vt100��Ӧ����
*/
// csi - ��������������(Control Sequence Introducer)��
// ����ͨ�����Ͳ��������������0���豸���ԣ�DA���������У� 'ESC [c' �� 'ESC [0c' ��
// Ҫ���ն�Ӧ��һ���豸���Կ������У�ESC Z�����������ͬ�����ն�����������������Ӧ
// �����������У��� 'ESC [?1;2c' ����ʾ�ն��Ǿ��и���Ƶ���ܵ�VT100�����նˡ�
147 #define RESPONSE "\033[?1;2c"
148
// ����ʹ�õ��ַ����������ϰ벿��ʱ��ͨ7����ASCII���룬��US�ַ������°벿�ֶ�Ӧ
// VT100�ն��豸�е������ַ�������ʾͼ���������ַ�����
149 static char * translations[] = {
150 /* normal 7-bit ascii */
151 " !\"#$%&'()*+,-./0123456789:;<=>?"
152 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
153 "`abcdefghijklmnopqrstuvwxyz{|}~ ",
154 /* vt100 graphics */
155 " !\"#$%&'()*+,-./0123456789:;<=>?"
156 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
157 "\004\261\007\007\007\007\370\361\007\007\275\267\326\323\327\304"
158 "\304\304\304\304\307\266\320\322\272\363\362\343\\007\234\007 "
159 };
160
161 #define NORM_TRANS (translations[0])
162 #define GRAF_TRANS (translations[1])
163
//// ���ٹ�굱ǰλ�á�
// ������currcons - ��ǰ�����ն˺ţ�new_x - ��������кţ�new_y - ��������кš�
// ���µ�ǰ���λ�ñ��� x,y���������������ʾ�ڴ��еĶ�Ӧλ�� pos���ú��������ȼ��
// ��������Ч�ԡ���������Ĺ���кų�����ʾ��������������߹���кŲ�������ʾ�����
// ���������˳���������µ�ǰ���������¹��λ�ö�Ӧ����ʾ�ڴ���λ��pos��
// ע�⣬�����е����б���ʵ������vc_cons[currcons]�ṹ�е���Ӧ�ֶΡ����º�����ͬ��
164 /* NOTE! gotoxy thinks x==video_num_columns is ok */
/* ע�⣡gotoxy������Ϊ x==video_num_columns ʱ����ȷ�� */
165 static inline void gotoxy(int currcons, int new_x,unsigned int new_y)
166 {
167 if (new_x > video_num_columns || new_y >= video_num_lines)
168 return;
169 x = new_x;
170 y = new_y;
171 pos = origin + y*video_size_row + (x<<1); // 1����2���ֽڱ�ʾ������x<<1��
172 }
173
//// ���ù�����ʼ��ʾ�ڴ��ַ��
// �ٴ����ѣ������б��������϶��� vc_cons[currcons] �ṹ�е���Ӧ�ֶΡ�
174 static inline void set_origin(int currcons)
175 {
// �����ж���ʾ�����͡� ���� EGA/VGA �������ǿ���ָ�������з�Χ�������й���������
// ��MDA��ɫ��ʾ��ֻ�ܽ��������������������ֻ�� EGA/VGA ������Ҫ���ù�����ʼ����ʾ
// �ڴ��ַ����ʼ���� origin ��Ӧ���У�������ʾ����������� EGA/VGA ��ɫģʽ��Ҳ����
// EGA/VGA��ɫģʽ����ô��ֱ�ӷ��ء����⣬����ֻ��ǰ̨����̨���в�������˵�ǰ����̨
// currcons������ǰ̨����̨ʱ�����Dz���Ҫ�����������ʼ�ж�Ӧ���ڴ����λ�á�
176 if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
177 return;
178 if (currcons != fg_console)
179 return;
// Ȼ������ʾ�Ĵ���ѡ��˿�video_port_reg���12����ѡ����ʾ�������ݼĴ���r12������
// д�������ʼ��ַ���ֽڡ����������ƶ�9λ��ʵ���ϱ�ʾ�����ƶ�8λ�ٳ���2����Ļ��1
// ���ַ���2�ֽڱ�ʾ������ѡ����ʾ�������ݼĴ���r13��Ȼ��д�������ʼ��ַ���ֽڡ���
// ���ƶ�1λ��ʾ����2��ͬ��������Ļ��1���ַ���2�ֽڱ�ʾ�����ֵ�����Ĭ����ʾ�ڴ�
// ��ʼλ��video_mem_base���в������������ EGA/VGA ��ɫģʽ��viedo_mem_base = ����
// �ڴ��ַ0xb8000��
180 cli();
181 outb_p(12, video_port_reg); // ѡ�����ݼĴ���r12�����������ʼλ�ø��ֽڡ�
182 outb_p(0xff&((origin-video_mem_base)>>9), video_port_val);
183 outb_p(13, video_port_reg); // ѡ�����ݼĴ���r13�����������ʼλ�õ��ֽڡ�
184 outb_p(0xff&((origin-video_mem_base)>>1), video_port_val);
185 sti();
186 }
187
//// ���Ͼ���һ�С�
// ����Ļ�������������ƶ�һ�У�������Ļ��������׳��ֵ����������ӿո��ַ�����������
// �������1�С��μ������б���˵����
188 static void scrup(int currcons)
189 {
// �����������������2�С�������������кŴ��ڵ���������кţ���������й��в���
// �����������⣬����EGA/VGA�������ǿ���ָ�������з�Χ�������й�����������MDA��
// ɫ��ʾ��ֻ�ܽ������������������ú�����EGA��MDA��ʾ���ͽ��зֱ����������ʾ����
// �� EGA����Ϊ���������ƶ��������ڴ����ƶ����������ȴ�����ʾ����EGA/VGA��ʾ����
// �������
190 if (bottom<=top)
191 return;
192 if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
193 {
// ����ƶ���ʼ��top=0���ƶ������ bottom = video_num_lines = 25�����ʾ������������
// �ƶ������ǰ�������Ļ�������ϽǶ�Ӧ����ʼ�ڴ�λ��origin ����Ϊ������һ�ж�Ӧ���ڴ�
// λ�ã�ͬʱҲ���ٵ�����ǰ����Ӧ���ڴ�λ���Լ���Ļĩ��ĩ���ַ�ָ��scr_end��λ�á�
// ��������Ļ�����ڴ���ʼλ��ֵoriginд����ʾ�������С�
194 if (!top && bottom == video_num_lines) {
195 origin += video_size_row;
196 pos += video_size_row;
197 scr_end += video_size_row;
// �����Ļ����ĩ������Ӧ����ʾ�ڴ�ָ��scr_end ������ʵ����ʾ�ڴ�ĩ�ˣ�����Ļ����
// ����һ�����������ж�Ӧ���ڴ������ƶ�����ʾ�ڴ����ʼλ��video_mem_start��������
// �������������ƶ����ֵ�����������ո��ַ���Ȼ�������Ļ�ڴ������ƶ�������������
// ������ǰ��Ļ��Ӧ�ڴ����ʼָ�롢���λ��ָ�����Ļĩ�˶�Ӧ�ڴ�ָ��scr_end��
// ���Ƕ����������Ƚ�����Ļ�ַ����� - 1���ж�Ӧ���ڴ������ƶ�����ʾ�ڴ���ʼλ��
// video_mem_start����Ȼ���������ڴ�λ�ô�����һ�пո������ַ����ݡ�
// %0 -eax(�����ַ�+����)��%1 -ecx��(��Ļ�ַ�����-1)����Ӧ���ַ���/2���Գ����ƶ�����
// %2 -edi(��ʾ�ڴ���ʼλ��video_mem_start)��%3 -esi(��Ļ�����ڴ���ʼλ��origin)��
// �ƶ�����[edi]��[esi]���ƶ�ecx�����֡�
198 if (scr_end > video_mem_end) {
199 __asm__("cld\n\t" // �巽��λ��
200 "rep\n\t" // �ظ�����������ǰ��Ļ�ڴ�
201 "movsl\n\t" // �����ƶ�����ʾ�ڴ���ʼ����
202 "movl _video_num_columns,%1\n\t"
203 "rep\n\t" // ������������ո��ַ���
204 "stosw"
205 ::"a" (video_erase_char),
206 "c" ((video_num_lines-1)*video_num_columns>>1),
207 "D" (video_mem_start),
208 "S" (origin)
209 :"cx","di","si");
210 scr_end -= origin-video_mem_start;
211 pos -= origin-video_mem_start;
212 origin = video_mem_start;
// ������������Ļĩ�˶�Ӧ���ڴ�ָ��scr_end û�г�����ʾ�ڴ��ĩ�� video_mem_end��
// ��ֻ������������������ַ����ո��ַ�����
// %0 -eax(�����ַ�+����)��%1 -ecx(��Ļ����)��%2 - edi�����1�п�ʼ����Ӧ�ڴ�λ�ã���
213 } else {
214 __asm__("cld\n\t"
215 "rep\n\t" // �ظ����������³�������
216 "stosw" // ��������ַ�(�ո��ַ�)��
217 ::"a" (video_erase_char),
218 "c" (video_num_columns),
219 "D" (scr_end-video_size_row)
220 :"cx","di");
221 }
// Ȼ�������Ļ���������ڴ���ʼλ��ֵoriginд����ʾ�������С�
222 set_origin(currcons);
// �����ʾ���������ƶ�������ʾ��ָ����top��ʼ��bottom�����е������������ƶ�1�У�
// ָ����top��ɾ������ʱֱ�ӽ���Ļ��ָ����top����Ļĩ�������ж�Ӧ����ʾ�ڴ�������
// ���ƶ�1�У������������³��ֵ�������������ַ���
// %0 - eax(�����ַ�+����)��%1 - ecx(top����1�п�ʼ��bottom������Ӧ���ڴ泤����)��
// %2 - edi(top���������ڴ�λ��)��%3 - esi(top+1���������ڴ�λ��)��
223 } else {
224 __asm__("cld\n\t"
225 "rep\n\t" // ѭ����������top+1��bottom��
226 "movsl\n\t" // ����Ӧ���ڴ���Ƶ�top�п�ʼ����
227 "movl _video_num_columns,%%ecx\n\t"
228 "rep\n\t" // ����������������ַ���
229 "stosw"
230 ::"a" (video_erase_char),
231 "c" ((bottom-top-1)*video_num_columns>>1),
232 "D" (origin+video_size_row*top),
233 "S" (origin+video_size_row*(top+1))
234 :"cx","di","si");
235 }
236 }
// �����ʾ���Ͳ���EGA������MDA ������ִ�������ƶ���������ΪMDA��ʾ���ƿ�ֻ��������
// �������һ��Զ�����������ʾ��Χ������������Զ�����ָ�룬�������ﲻ����Ļ���ݶ�Ӧ��
// �泬����ʾ�ڴ�������������������������EGA�������ƶ������ȫһ����
237 else /* Not EGA/VGA */
238 {
239 __asm__("cld\n\t"
240 "rep\n\t"
241 "movsl\n\t"
242 "movl _video_num_columns,%%ecx\n\t"
243 "rep\n\t"
244 "stosw"
245 ::"a" (video_erase_char),
246 "c" ((bottom-top-1)*video_num_columns>>1),
247 "D" (origin+video_size_row*top),
248 "S" (origin+video_size_row*(top+1))
249 :"cx","di","si");
250 }
251 }
252
//// ���¾���һ�С�
// ����Ļ�������������ƶ�һ�У���Ӧ��Ļ�����������������ƶ�1�С������ƶ���ʼ�е���
// ������һ���С��μ������б���˵�������������� scrup()���ƣ�ֻ��Ϊ�����ƶ���ʾ�ڴ�
// ����ʱ����������ݸ��ǵ����⣬���Ʋ�������������еģ����ȴ���Ļ������2�е����
// һ���ַ���ʼ���Ƶ����һ�У��ٽ�������3�и��Ƶ�������2�еȵȡ���Ϊ��ʱ��EGA/
// VGA��ʾ���ͺ�MDA���͵Ĵ���������ȫһ�������Ըú���ʵ����û�б�Ҫд������ͬ�Ĵ�
// �롣������if��else�����еIJ�����ȫһ����
253 static void scrdown(int currcons)
254 {
// ͬ���������������������2�С�������������кŴ��ڵ���������кţ���������й�
// �в��������������⣬����EGA/VGA�������ǿ���ָ�������з�Χ�������й�����������
// MDA��ɫ��ʾ��ֻ�ܽ��������������������ڴ��������ƶ�����ƶ�����ǰ����̨ռ����ʾ��
// ���ڴ����ʼλ�ã���˲��ᷢ����Ļ����ĩ������Ӧ����ʾ�ڴ�ָ��scr_end����ʵ����ʾ
// �ڴ�ĩ�˵��������������ֻ��Ҫ������ͨ���ڴ������ƶ������
255 if (bottom <= top)
256 return;
257 if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
258 {
// %0 - eax(�����ַ�+����)��%1 - ecx(top�е� bottom-1 �е���������Ӧ���ڴ泤����)��
// %2 - edi(�������½����һ������λ��)��%3 - esi(���ڵ�����2�����һ������λ��)��
// �ƶ�����[esi]��[edi]���ƶ�ecx�����֡�
259 __asm__("std\n\t" // �÷���λ����
260 "rep\n\t" // �ظ������������ƶ���top�е�
261 "movsl\n\t" // bottom-1�ж�Ӧ���ڴ����ݡ�
262 "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
/* %edi�Ѽ�4����Ҳ�Ƿ���������ַ�*/
263 "movl _video_num_columns,%%ecx\n\t"
264 "rep\n\t" // �������ַ������Ϸ������С�
265 "stosw"
266 ::"a" (video_erase_char),
267 "c" ((bottom-top-1)*video_num_columns>>1),
268 "D" (origin+video_size_row*bottom-4),
269 "S" (origin+video_size_row*(bottom-1)-4)
270 :"ax","cx","di","si");
271 }
// �������EGA��ʾ���ͣ���ִ�����²�������������ȫһ������
272 else /* Not EGA/VGA */
273 {
274 __asm__("std\n\t"
275 "rep\n\t"
276 "movsl\n\t"
277 "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
278 "movl _video_num_columns,%%ecx\n\t"
279 "rep\n\t"
280 "stosw"
281 ::"a" (video_erase_char),
282 "c" ((bottom-top-1)*video_num_columns>>1),
283 "D" (origin+video_size_row*bottom-4),
284 "S" (origin+video_size_row*(bottom-1)-4)
285 :"ax","cx","di","si");
286 }
287 }
288
//// �����ͬ��λ������һ�С�
// ������û�д������һ���ϣ���ֱ���Ĺ�굱ǰ�б���y++������������Ӧ��ʾ�ڴ�
// λ��pos������һ���ַ�����Ӧ���ڴ泤�ȣ����������Ҫ����Ļ������������һ�С�
// ��������lf��line feed ���У���ָ���������ַ�LF��
289 static void lf(int currcons)
290 {
291 if (y+1<bottom) {
292 y++;
293 pos += video_size_row; // ������Ļһ��ռ���ڴ���ֽ�����
294 return;
295 }
296 scrup(currcons); // ����Ļ������������һ�С�
297 }
298
//// �����ͬ������һ�С�
// �����겻����Ļ��һ���ϣ���ֱ���Ĺ�굱ǰ�б���y--������������Ӧ��ʾ�ڴ�λ��
// pos����ȥ��Ļ��һ���ַ�����Ӧ���ڴ泤���ֽ�����������Ҫ����Ļ������������һ�С�
// ��������ri��reverse index ������������ָ�����ַ�RI��ת�����С�ESC M����
299 static void ri(int currcons)
300 {
301 if (y>top) {
302 y--;
303 pos -= video_size_row; // ��ȥ��Ļһ��ռ���ڴ���ֽ�����
304 return;
305 }
306 scrdown(currcons); // ����Ļ������������һ�С�
307 }
308
// ���ص���1�У�0�У���
// ��������Ӧ�ڴ�λ��pos����������к�*2 ����0�е���������ж�Ӧ���ڴ��ֽڳ��ȡ�
// ��������cr��carriage return �س���ָ�������Ŀ����ַ��ǻس��ַ���
309 static void cr(int currcons)
310 {
311 pos -= x<<1; // ��ȥ0�е���괦ռ�õ��ڴ��ֽ�����
312 x=0;
313 }
314
// �������ǰһ�ַ����ÿո��������del - delete ɾ������
// ������û�д���0�У�����Ӧ�ڴ�λ��pos����2�ֽڣ���Ӧ��Ļ��һ���ַ�����
// Ȼ��ǰ��������ֵ��1�������������λ�ô��ַ�������
315 static void del(int currcons)
316 {
317 if (x) {
318 pos -= 2;
319 x--;
320 *(unsigned short *)pos = video_erase_char;
321 }
322 }
323
//// ɾ����Ļ������λ����صIJ��֡�
// ANSI�������У�'ESC [ Ps J'��Ps =0 -ɾ����괦����Ļ�ˣ�1 -ɾ����Ļ��ʼ����괦��
// 2 - ����ɾ����������������ָ���Ŀ������о������ֵ��ִ������λ����ص�ɾ��������
// �����ڲ����ַ�����ʱ���λ�ò��䡣
// ��������csi_J ��CSI - Control Sequence Introducer�����������������룩ָ���Կ���
// ����CSI Ps J���������
// ������vpar - ��Ӧ�������������Ps��ֵ��
324 static void csi_J(int currcons, int vpar)
325 {
326 long count __asm__("cx"); // ��Ϊ�Ĵ���������
327 long start __asm__("di");
328
// ���ȸ�����������ֱ�������Ҫɾ�����ַ�����ɾ����ʼ����ʾ�ڴ�λ�á�
329 switch (vpar) {
330 case 0: /* erase from cursor to end of display */
331 count = (scr_end-pos)>>1; /* ������굽��Ļ�������ַ� */
332 start = pos;
333 break;
334 case 1: /* erase from start to cursor */
335 count = (pos-origin)>>1; /* ɾ������Ļ��ʼ����괦���ַ� */
336 start = origin;
337 break;
338 case 2: /* erase whole display */ /* ɾ��������Ļ�ϵ������ַ� */
339 count = video_num_columns * video_num_lines;
340 start = origin;
341 break;
342 default:
343 return;
344 }
// Ȼ��ʹ�ò����ַ���д��ɾ���ַ��ĵط���
// %0 -ecx(ɾ�����ַ���count)��%1 -edi(ɾ��������ʼ��ַ)��%2 -eax������IJ����ַ�����
345 __asm__("cld\n\t"
346 "rep\n\t"
347 "stosw\n\t"
348 ::"c" (count),
349 "D" (start),"a" (video_erase_char)
350 :"cx","di");
351 }
352
//// ɾ��һ��������λ����صIJ��֡�
// ANSIת���ַ����У�'ESC [ Ps K'��Ps = 0 ɾ������β��1 �ӿ�ʼɾ����2 ���ж�ɾ������
// ���������ݲ���������������еIJ��ֻ������ַ���������������Ļ�������ַ�����Ӱ����
// ���ַ����������ַ����������ڲ����ַ�����ʱ���λ�ò��䡣
// ������par - ��Ӧ�������������Ps��ֵ��
353 static void csi_K(int currcons, int vpar)
354 {
355 long count __asm__("cx"); // ���üĴ���������
356 long start __asm__("di");
357
// ���ȸ�����������ֱ�������Ҫɾ�����ַ�����ɾ����ʼ����ʾ�ڴ�λ�á�
358 switch (vpar) {
359 case 0: /* erase from cursor to end of line */
360 if (x>=video_num_columns) /* ɾ����굽��β�����ַ� */
361 return;
362 count = video_num_columns-x;
363 start = pos;
364 break;
365 case 1: /* erase from start of line to cursor */
366 start = pos - (x<<1); /* ɾ�����п�ʼ����괦 */
367 count = (x<video_num_columns)?x:video_num_columns;
368 break;
369 case 2: /* erase whole line */ /* �������ַ�ȫɾ�� */
370 start = pos - (x<<1);
371 count = video_num_columns;
372 break;
373 default:
374 return;
375 }
// Ȼ��ʹ�ò����ַ���дɾ���ַ��ĵط���
// %0 - ecx(ɾ���ַ���count)��%1 -edi(ɾ��������ʼ��ַ)��%2 -eax������IJ����ַ�����
376 __asm__("cld\n\t"
377 "rep\n\t"
378 "stosw\n\t"
379 ::"c" (count),
380 "D" (start),"a" (video_erase_char)
381 :"cx","di");
382 }
383
//// ������ʾ�ַ����ԡ�
// ANSIת�����У�'ESC [ Ps;Ps m'��Ps = 0 - Ĭ�����ԣ�1 - ���岢������4 - �»��ߣ�
// 5 - ��˸��7 - ���ԣ�22 - �Ǵ��壻24 - ���»��ߣ�25 - ����˸��27 - ���ԣ�
// 30--38 - ����ǰ��ɫ�ʣ�39 - Ĭ��ǰ��ɫ��White����40--48 - ���ñ���ɫ�ʣ�
// 49 - Ĭ�ϱ���ɫ��Black����
// �ÿ������и��ݲ��������ַ���ʾ���ԡ��Ժ����з��͵��ն˵��ַ�����ʹ������ָ������
// �ԣ�ֱ���ٴ�ִ�б������������������ַ���ʾ�����ԡ�
384 void csi_m(int currcons )
385 {
386 int i;
387
// һ�����������п��Դ��ж����ͬ�����������洢������par[]�С�������ݽ��յ��IJ���
// ����npar��ѭ��������������Ps��
// ���Ps = 0����ѵ�ǰ�������̨�����ʾ���ַ���������ΪĬ������def_attr����ʼ��ʱ
// def_attr�ѱ����ó�0x07���ڵװ��֣���
// ���Ps = 1����ѵ�ǰ�������̨�����ʾ���ַ���������Ϊ�����������ʾ�� ����Dz�ɫ
// ��ʾ������ַ����Ի���0x08���ַ���������ʾ������ǵ�ɫ��ʾ�������ַ����»�����ʾ��
// ���Ps = 4����Բ�ɫ�͵�ɫ��ʾ���в�ͬ�Ĵ���������ʱ���Dz�ɫ��ʾ��ʽ�������ַ���
// �»�����ʾ������Dz�ɫ��ʾ����ô��ԭ��vc_bold_attr������-1ʱ��λ�䱳��ɫ������
// �Ļ��Ͱ�ǰ��ɫȡ������ȡ����ǰ��ɫ�뱳��ɫ��ͬ���Ͱ�ǰ��ɫ��1��ȡ��һ����ɫ��
388 for (i=0;i<=npar;i++)
389 switch (par[i]) {
390 case 0: attr=def_attr;break; /* default */
391 case 1: attr=(iscolor?attr|0x08:attr|0x0f);break; /* bold */
392 /*case 4: attr=attr|0x01;break;*/ /* underline */
393 case 4: /* bold */
394 if (!iscolor)
395 attr |= 0x01; // ��ɫ����»�����ʾ��
396 else
397 { /* check if forground == background */
398 if (vc_cons[currcons].vc_bold_attr != -1)
399 attr = (vc_cons[currcons].vc_bold_attr&0x0f)|(0xf0&(attr));
400 else
401 { short newattr = (attr&0xf0)|(0xf&(~attr));
402 attr = ((newattr&0xf)==((attr>>4)&0xf)?
403 (attr&0xf0)|(((attr&0xf)+1)%0xf):
404 newattr);
405 }
406 }
407 break;
// ���Ps = 5����ѵ�ǰ�������̨�����ʾ���ַ�����Ϊ��˸�����������ֽڱ���λ7��1��
// ���Ps = 7����ѵ�ǰ�������̨�����ʾ���ַ�����Ϊ���ԣ�����ǰ���ͱ���ɫ������
// ���Ps = 22����ȡ������ַ��ĸ�������ʾ��ȡ��������ʾ����
// ���Ps = 24������ڵ�ɫ��ʾ��ȡ������ַ����»�����ʾ�����ڲ�ɫ��ʾ����ȡ����ɫ��
// ���Ps = 25����ȡ������ַ�����˸��ʾ��
// ���Ps = 27����ȡ������ַ��ķ��ԡ�
// ���Ps = 39����λ����ַ���ǰ��ɫΪĬ��ǰ��ɫ����ɫ����
// ���Ps = 49����λ����ַ��ı���ɫΪĬ�ϱ���ɫ����ɫ����
408 case 5: attr=attr|0x80;break; /* blinking */
409 case 7: attr=(attr<<4)|(attr>>4);break; /* negative */
410 case 22: attr=attr&0xf7;break; /* not bold */
411 case 24: attr=attr&0xfe;break; /* not underline */
412 case 25: attr=attr&0x7f;break; /* not blinking */
413 case 27: attr=def_attr;break; /* positive image */
414 case 39: attr=(attr & 0xf0)|(def_attr & 0x0f); break;
415 case 49: attr=(attr & 0x0f)|(def_attr & 0xf0); break;
// ��Ps��par[i]��Ϊ����ֵʱ����������ָ����ǰ��ɫ��ɫ�����Ps = 30..37����������
// ǰ��ɫ�����Ps=40..47���������ñ���ɫ���й���ɫֵ��μ������˵����
416 default:
417 if (!can_do_colour)
418 break;
419 iscolor = 1;
420 if ((par[i]>=30) && (par[i]<=38)) // ����ǰ��ɫ��
421 attr = (attr & 0xf0) | (par[i]-30);
422 else /* Background color */
423 if ((par[i]>=40) && (par[i]<=48)) // ���ñ���ɫ��
424 attr = (attr & 0x0f) | ((par[i]-40)<<4);
425 else
426 break;
427 }
428 }
429
//// ������ʾ��ꡣ
// ���ݹ���Ӧ��ʾ�ڴ�λ��pos��������ʾ������������ʾλ�á�
430 static inline void set_cursor(int currcons)
431 {
// ��Ȼ������Ҫ������ʾ��꣬˵���м��̲����������Ҫ�ָ����к�����������ʱ����ֵ��
// ���⣬��ʾ���Ŀ���̨������ǰ̨����̨���������ǰ������̨��currcons����ǰ̨��
// ��̨�����̷��ء�
432 blankcount = blankinterval; // ��λ���������ļ���ֵ��
433 if (currcons != fg_console)
434 return;
// Ȼ��ʹ�������Ĵ����˿�ѡ����ʾ�������ݼĴ���r14����굱ǰ��ʾλ�ø��ֽڣ�������
// д���굱ǰλ�ø��ֽڣ������ƶ�9λ��ʾ���ֽ��Ƶ����ֽ��ٳ���2�����������Ĭ��
// ��ʾ�ڴ�����ġ���ʹ�������Ĵ���ѡ��r15��������굱ǰλ�õ��ֽ�д�����С�
435 cli();
436 outb_p(14, video_port_reg);
437 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
438 outb_p(15, video_port_reg);
439 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
440 sti();
441 }
442
// ���ع�ꡣ
// �ѹ�����õ���ǰ�������̨���ڵ�ĩ�ˣ������ع������á�
443 static inline void hide_cursor(int currcons)
444 {
// ����ʹ�������Ĵ����˿�ѡ����ʾ�������ݼĴ���r14����굱ǰ��ʾλ�ø��ֽڣ���Ȼ��
// д���굱ǰλ�ø��ֽڣ������ƶ�9λ��ʾ���ֽ��Ƶ����ֽ��ٳ���2�����������Ĭ��
// ��ʾ�ڴ�����ġ���ʹ�������Ĵ���ѡ��r15��������굱ǰλ�õ��ֽ�д�����С�
445 outb_p(14, video_port_reg);
446 outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val);
447 outb_p(15, video_port_reg);
448 outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
449 }
450
//// ���Ͷ�VT100����Ӧ���С�
// ��Ϊ��Ӧ���������ն������������豸���ԣ�DA��������ͨ�����Ͳ��������������0��DA
// �������У�'ESC [ 0c' �� 'ESC Z'��Ҫ���ն˷���һ���豸���ԣ�DA���������У��ն���
// ��85���϶����Ӧ�����У��� 'ESC [?1;2c'������Ӧ���������У������и����������ն�
// �Ǿ��и���Ƶ���ܵ�VT100�����նˡ����������ǽ�Ӧ�����з������������У���ʹ��
// copy_to_cooked()������������븨�������С�
451 static void respond(int currcons, struct tty_struct * tty)
452 {
453 char * p = RESPONSE; // �����ڵ�147���ϡ�
454
455 cli();
456 while (*p) { // ��Ӧ�����з�������С�
457 PUTCH(*p,tty->read_q); // ���ַ����롣include/linux/tty.h��46�С�
458 p++;
459 }
460 sti(); // ת���ɹ淶ģʽ�����븨�������У���
461 copy_to_cooked(tty); // tty_io.c��120��
462 }
463
//// �ڹ�괦����һ�ո��ַ���
// �ѹ�꿪ʼ���������ַ�����һ���������ַ������ڹ�����ڴ���
464 static void insert_char(int currcons)
465 {
466 int i=x;
467 unsigned short tmp, old = video_erase_char; // �����ַ��������ԣ���
468 unsigned short * p = (unsigned short *) pos; // ����Ӧ�ڴ�λ�á�
469
470 while (i++<video_num_columns) {
471 tmp=*p;
472 *p=old;
473 old=tmp;
474 p++;
475 }
476 }
477
//// �ڹ�괦����һ�С�
// ����Ļ���ڴӹ�������е����ڵ��������¾���һ�С���꽫�����µĿ����ϡ�
478 static void insert_line(int currcons)
479 {
480 int oldtop,oldbottom;
481
// ���ȱ�����Ļ���ھ�����ʼ��top�������bottomֵ��Ȼ��ӹ������������Ļ��������
// ����һ�С����ָ���Ļ���ھ�����ʼ��top�������bottom��ԭ��ֵ��
482 oldtop=top;
483 oldbottom=bottom;
484 top=y; // ������Ļ������ʼ�кͽ����С�
485 bottom = video_num_lines;
486 scrdown(currcons); // �ӹ�꿪ʼ������Ļ�������¹���һ�С�
487 top=oldtop;
488 bottom=oldbottom;
489 }
490
//// ɾ��һ���ַ���
// ɾ����괦��һ���ַ�������ұߵ������ַ�����һ��
491 static void delete_char(int currcons)
492 {
493 int i;
494 unsigned short * p = (unsigned short *) pos;
495
// ������ĵ�ǰ��λ��x������Ļ�����У��ء�����ӹ����һ���ַ���ʼ����ĩ����
// �ַ�����һ��Ȼ�������һ���ַ�����������ַ���
496 if (x>=video_num_columns)
497 return;
498 i = x;
499 while (++i < video_num_columns) { // ����������ַ�����1��
500 *p = *(p+1);
501 p++;
502 }
503 *p = video_erase_char; // �����������ַ���
504 }
505
//// ɾ����������С�
// ɾ��������ڵ�һ�У����ӹ�������п�ʼ��Ļ�����Ͼ�һ�С�
506 static void delete_line(int currcons)
507 {
508 int oldtop,oldbottom;
509
// ���ȱ�����Ļ������ʼ��top�������bottomֵ��Ȼ��ӹ������������Ļ�������Ϲ���
// һ�С����ָ���Ļ������ʼ��top�������bottom��ԭ��ֵ��
510 oldtop=top;
511 oldbottom=bottom;
512 top=y; // ������Ļ������ʼ�к�����С�
513 bottom = video_num_lines;
514 scrup(currcons); // �ӹ�꿪ʼ������Ļ�������Ϲ���һ�С�
515 top=oldtop;
516 bottom=oldbottom;
517 }
518
//// �ڹ�괦����nr���ַ���
// ANSIת���ַ����У�'ESC [ Pn @'���ڵ�ǰ��괦����1�������ո��ַ���Pn�Dz������
// ������Ĭ����1����꽫��Ȼ���ڵ�1������Ŀո��ַ������ڹ�����ұ߽���ַ������ơ�
// �����ұ߽���ַ�������ʧ��
// ���� nr = ת���ַ������еIJ���Pn��
519 static void csi_at(int currcons, unsigned int nr)
520 {
// ���������ַ�������һ���ַ��������Ϊһ���ַ������������ַ���nrΪ0�������1��
// �ַ���Ȼ��ѭ������ָ�����ո��ַ���
521 if (nr > video_num_columns)
522 nr = video_num_columns;
523 else if (!nr)
524 nr = 1;
525 while (nr--)
526 insert_char(currcons);
527 }
528
//// �ڹ��λ�ô�����nr�С�
// ANSIת���ַ����У�'ESC [ Pn L'���ÿ��������ڹ�괦����1�л���п��С�������ɺ�
// ���λ�ò��䡣�����б�����ʱ��������¹��������ڵ��������ƶ�����������ʾҳ���о�
// ��ʧ��
// ���� nr = ת���ַ������еIJ���Pn��
529 static void csi_L(int currcons, unsigned int nr)
530 {
// ������������������Ļ������������Ϊ��Ļ��ʾ����������������nrΪ0�������1�С�
// Ȼ��ѭ������ָ������nr�Ŀ��С�
531 if (nr > video_num_lines)
532 nr = video_num_lines;
533 else if (!nr)
534 nr = 1;
535 while (nr--)
536 insert_line(currcons);
537 }
538
//// ɾ����괦��nr���ַ���
// ANSIת�����У�'ESC [ Pn P'���ÿ������дӹ�괦ɾ��Pn���ַ�����һ���ַ���ɾ��ʱ��
// ����������ַ������ơ�������ұ߽紦����һ�����ַ���������Ӧ�������һ�������ַ�
// ��ͬ�����������˼�������ʹ���ַ���Ĭ�����ԣ��ڵװ��ֿո�0x0720�������ÿ��ַ���
// ���� nr = ת���ַ������еIJ���Pn��
539 static void csi_P(int currcons, unsigned int nr)
540 {
// ���ɾ�����ַ�������һ���ַ��������Ϊһ���ַ�������ɾ���ַ���nrΪ0����ɾ��1��
// �ַ���Ȼ��ѭ��ɾ����괦ָ���ַ���nr��
541 if (nr > video_num_columns)
542 nr = video_num_columns;
543 else if (!nr)
544 nr = 1;
545 while (nr--)
546 delete_char(currcons);
547 }
548
//// ɾ����괦��nr�С�
// ANSIת�����У�'ESC [ Pn M'���ÿ��������ڹ��������ڣ��ӹ�������п�ʼɾ��1�л��
// �С����б�ɾ��ʱ�����������ڵı�ɾ�����µ��л������ƶ������һ������������1���С�
// ��Pn������ʾҳ��ʣ�������������н�ɾ����Щʣ���У����Թ��������ⲻ�����á�
// ���� nr = ת���ַ������еIJ���Pn��
549 static void csi_M(int currcons, unsigned int nr)
550 {
// ���ɾ��������������Ļ������������Ϊ��Ļ��ʾ����������ɾ��������nrΪ0����ɾ��
// 1�С�Ȼ��ѭ��ɾ��ָ������nr��
551 if (nr > video_num_lines)
552 nr = video_num_lines;
553 else if (!nr)
554 nr=1;
555 while (nr--)
556 delete_line(currcons);
557 }
558
//// ���浱ǰ���λ�á�
559 static void save_cur(int currcons)
560 {
561 saved_x=x;
562 saved_y=y;
563 }
564
//// �ָ�����Ĺ��λ�á�
565 static void restore_cur(int currcons)
566 {
567 gotoxy(currcons,saved_x, saved_y);
568 }
569
570
// ���ö�ٶ�����������con_write()�����д���ת�����л�������еĽ�����ESnormal�dz�
// ʼ����״̬��Ҳ��ת���������д������ʱ��״̬��
// ESnormal - ��ʾ���ڳ�ʼ����״̬����ʱ�����յ�������ͨ��ʾ�ַ�������ַ�ֱ����ʾ
// ����Ļ�ϣ������յ����ǿ����ַ�������س��ַ�������Թ��λ�ý������á�
// ���մ�����һ��ת���������У�����Ҳ�᷵�ص���״̬��
// ESesc - ��ʾ���յ�ת�����������ַ�ESC��0x1b = 033 = 27��������ڴ�״̬�½���
// ��һ��'['�ַ�����˵��ת�����������룬������ת��ESsquareȥ����������
// �Ͱѽ��յ����ַ���Ϊת������������������ѡ���ַ���ת������'ESC (' ��
// 'ESC )'������ʹ�õ�����״̬ESsetgraph�������������豸�����ַ�������
// 'ESC P'������ʹ�õ�����״̬ESsetterm��������
// ESsquare - ��ʾ�Ѿ����յ�һ���������������루'ESC ['������ʾ���յ�����һ��������
// �С����DZ�״ִ̬�в�������par[]�����ʼ�������������ʱ���յ�������һ
// ��'['�ַ������ʾ�յ���'ESC [['���С��������Ǽ��̹��ܼ����������У���
// ����ת�� Esfunckey ȥ����������������Ҫ�����տ������еIJ�����������
// ״̬Esgetpars��ֱ�ӽ����״̬ȥ���ղ��������еIJ����ַ���
// ESgetpars - ��״̬��ʾ���Ǵ�ʱҪ���տ������еIJ���ֵ��������ʮ��������ʾ�����ǰ�
// ���յ��������ַ�ת������ֵ�����浽par[]�����С�����յ�һ���ֺ� ';'��
// ����ά���ڱ�״̬�����ѽ��յ��IJ���ֵ����������par[]��һ���С�������
// �����ַ���ֺţ�˵����ȡ�����в�������ô��ת�Ƶ�״̬ESgotparsȥ������
// ESgotpars - ��ʾ�����Ѿ����յ�һ�������Ŀ������С���ʱ���ǿ��Ը��ݱ�״̬���յ��Ľ�
// β�ַ�����Ӧ�������н��д����������ڴ���֮ǰ�����������ESsquare ״̬
// �յ��� '?'��˵������������ն��豸˽�����С����ں˲���֧�ֶ��������е�
// ��������������ֱ�ӻָ��� ESnormal ״̬�������ȥִ����Ӧ�������С�����
// �д������Ͱ�״̬�ָ��� ESnormal��
// ESfunckey - ��ʾ���ǽ��յ��˼����Ϲ��ܼ�������һ�����С����Dz�����ʾ�����ǻָ�����
// ��״̬ESnormal��
// ESsetterm - ��ʾ�����豸�����ַ�������״̬��DCS������ʱ���յ��ַ� 'S'����ָ���ʼ
// ����ʾ�ַ����ԡ����յ����ַ���'L'��'l'��������ر�������ʾ��ʽ��
// ESsetgraph -��ʾ�յ������ַ���ת������'ESC (' �� 'ESC )'�����Ƿֱ�����ָ��G0��G1
// ���õ��ַ�������ʱ���յ��ַ� '0'����ѡ��ͼ���ַ�����ΪG0��G1�����յ�
// ���ַ��� 'B'����ѡ����ͨASCII�ַ�����ΪG0��G1���ַ�����
571 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
572 ESsetterm, ESsetgraph };
573
//// ����̨д������
// ���ն˶�Ӧ��ttyд���������ȡ�ַ������ÿ���ַ����з��������ǿ����ַ���ת������
// ���У�����й�궨λ���ַ�ɾ���ȵĿ��ƴ�����������ͨ�ַ���ֱ���ڹ�괦��ʾ��
// ���� tty�ǵ�ǰ����̨ʹ�õ�tty�ṹָ�롣
574 void con_write(struct tty_struct * tty)
575 {
576 int nr;
577 char c;
578 int currcons;
579
// �ú������ȸ��ݵ�ǰ����̨ʹ�õ�tty��tty���е���λ��ȡ�ö�Ӧ�Ŀ���̨��currcons��
// Ȼ��������CHARS()��Ŀǰttyд�����к��е��ַ���nr����ѭ��ȡ�����е�ÿ���ַ�����
// ���������������ǰ����̨���ڽ��յ����̻��������ͣ����簴��Ctrl-S��������
// ֹͣ״̬����ô��������ֹͣ����д�����е��ַ����˳����������⣬���ȡ�����ǿ����ַ�
// CAN��24���� SUB��26������ô������ת�����������ڼ��յ��ģ������в���ִ�ж�������
// ֹ��ͬʱ��ʾ�����ַ���ע�⣬con_write()����ֻ����ȡ�����ַ���ʱд�����е�ǰ����
// ���ַ������п�����һ�����б��ŵ�д�����ڼ��ȡ�ַ�������˱�����ǰһ���˳�ʱstate
// �п��������ڴ���ת���������е�����״̬�ϡ�
580 currcons = tty - tty_table;
581 if ((currcons>=MAX_CONSOLES) || (currcons<0))
582 panic("con_write: illegal tty");
583
584 nr = CHARS(tty->write_q); // ȡд�������ַ�������tty.h�ļ��С�
585 while (nr--) {
586 if (tty->stopped)
587 break;
588 GETCH(tty->write_q,c); // ȡ1�ַ���c�С�
589 if (c == 24 || c == 26) // �����ַ� CAN��SUB - ȡ�����滻��
590 state = ESnormal;
591 switch(state) {
// �����д������ȡ�����ַ�����ͨ��ʾ�ַ����룬��ֱ�Ӵӵ�ǰӳ���ַ�����ȡ����Ӧ����ʾ
// �ַ������ŵ���ǰ�����������ʾ�ڴ�λ�ô�����ֱ����ʾ���ַ���Ȼ��ѹ��λ������һ��
// �ַ�λ�á�����أ�����ַ����ǿ����ַ�Ҳ������չ�ַ�����(31<c<127)����ô������ǰ��
// �괦����ĩ�˻�ĩ�����⣬����Ƶ�����ͷ�С����������λ�ö�Ӧ���ڴ�ָ��pos��Ȼ
// ���ַ�cд����ʾ�ڴ���pos���������������1�У�ͬʱҲ��pos��Ӧ���ƶ�2���ֽڡ�
592 case ESnormal:
593 if (c>31 && c<127) { // ����ͨ��ʾ�ַ���
594 if (x>=video_num_columns) { // Ҫ���У�
595 x -= video_num_columns;
596 pos -= video_size_row;
597 lf(currcons);
598 }
599 __asm__("movb %2,%%ah\n\t" // д�ַ���
600 "movw %%ax,%1\n\t"
601 ::"a" (translate[c-32]),
602 "m" (*(short *)pos),
603 "m" (attr)
604 :"ax");
605 pos += 2;
606 x++;
// ����ַ�c��ת���ַ�ESC����ת��״̬state��ESesc��637�У���
607 } else if (c==27) // ESC - ת������ַ���
608 state=ESesc;
// ���c�ǻ��з�LF(10)����ֱ�Ʊ���VT(11)����ҳ��FF(12)�������ƶ�����1�С�
609 else if (c==10 || c==11 || c==12)
610 lf(currcons);
// ���c�ǻس���CR(13)������ƶ���ͷ�У�0�У���
611 else if (c==13) // CR - �س���
612 cr(currcons);
// ���c��DEL(127)���������ַ�����(�ÿո��ַ����)����������Ƶ�������λ�á�
613 else if (c==ERASE_CHAR(tty))
614 del(currcons);
// ���c��BS(backspace,8)���������1����Ӧ��������Ӧ�ڴ�λ��ָ��pos��
615 else if (c==8) { // BS - ���ˡ�
616 if (x) {
617 x--;
618 pos -= 2;
619 }
// ����ַ�c��ˮƽ�Ʊ���HT(9)������Ƶ�8�ı������ϡ�����ʱ�������������Ļ���
// ����������Ƶ���һ���ϡ�
620 } else if (c==9) { // HT - ˮƽ�Ʊ���
621 c=8-(x&7);
622 x += c;
623 pos += c<<1;
624 if (x>video_num_columns) {
625 x -= video_num_columns;
626 pos -= video_size_row;
627 lf(currcons);
628 }
629 c=9;
// ����ַ�c�������BEL(7)������÷�����������������������
630 } else if (c==7) // BEL - ���塣
631 sysbeep();
// ���c�ǿ����ַ�SO��14����SI��15��������Ӧѡ���ַ���G1��G0��Ϊ��ʾ�ַ�����
632 else if (c == 14) // SO - ������ʹ��G1��
633 translate = GRAF_TRANS;
634 else if (c == 15) // SI - ������ʹ��G0��
635 translate = NORM_TRANS;
636 break;
// �����ESnormal״̬�յ�ת���ַ�ESC(0x1b = 033 = 27)����ת����״̬��������״̬��C1
// �п����ַ���ת���ַ����д������������Ĭ�ϵ�״̬����ESnormal��
637 case ESesc:
638 state = ESnormal;
639 switch (c)
640 {
641 case '[': // ESC [ - ��CSI����
642 state=ESsquare;
643 break;
644 case 'E': // ESC E - �������1�л�0�С�
645 gotoxy(currcons,0,y+1);
646 break;
647 case 'M': // ESC M - �������1��
648 ri(currcons);
649 break;
650 case 'D': // ESC D - �������1��
651 lf(currcons);
652 break;
653 case 'Z': // ESC Z - �豸���Բ�ѯ��
654 respond(currcons,tty);
655 break;
656 case '7': // ESC 7 - ������λ�á�
657 save_cur(currcons);
658 break;
659 case '8': // ESC 8 - �ָ�����Ĺ��ԭλ�á�
660 restore_cur(currcons);
661 break;
662 case '(': case ')': // ESC (��ESC ) - ѡ���ַ�����
663 state = ESsetgraph;
664 break;
665 case 'P': // ESC P - �����ն˲�����
666 state = ESsetterm;
667 break;
668 case '#': // ESC # - ���������ԡ�
669 state = -1;
670 break;
671 case 'c': // ESC c - ��λ���ն˳�ʼ���á�
672 tty->termios = DEF_TERMIOS;
673 state = restate = ESnormal;
674 checkin = 0;
675 top = 0;
676 bottom = video_num_lines;
677 break;
678 /* case '>': Numeric keypad */
679 /* case '=': Appl. keypad */
680 }
681 break;
// �����״̬ESesc����ת���ַ�ESC��ʱ�յ��ַ�'['���������CSI�������У�����ת��״
// ̬ESsequare�����������ȶ�ESCת�����б������������par[]���㣬��������nparָ��
// ��������������ǿ�ʼ����ȡ����״̬ESgetpars��������յ����ַ�����'?'����ֱ��ת
// ��״̬ESgetparsȥ�����������յ����ַ���'?'��˵������������ն��豸˽�����У�����
// ����һ�������ַ�������ȥ����һ�ַ����ٵ�״̬ ESgetpars ȥ�������봦�������ʱ����
// �����ַ�����'['����ô�����յ��˼��̹��ܼ����������У�����������һ״̬ΪESfunckey��
// ����ֱ�ӽ���ESgetpars״̬����������
682 case ESsquare:
683 for(npar=0;npar<NPAR;npar++) // ��ʼ���������顣
684 par[npar]=0;
685 npar=0;
686 state=ESgetpars;
687 if (c =='[') /* Function key */ // 'ESC [['�ǹ��ܼ���
688 { state=ESfunckey;
689 break;
690 }
691 if (ques=(c=='?'))
692 break;
// ��״̬��ʾ���Ǵ�ʱҪ���տ������еIJ���ֵ��������ʮ��������ʾ�����ǰѽ��յ���������
// ��ת������ֵ�����浽par[]�����С�����յ�һ���ֺ� ';'������ά���ڱ�״̬�����ѽ�
// �յ��IJ���ֵ����������par[]��һ���С������������ַ���ֺţ�˵����ȡ�����в�������
// ô��ת�Ƶ�״̬ESgotparsȥ������
693 case ESgetpars:
694 if (c==';' && npar<NPAR-1) {
695 npar++;
696 break;
697 } else if (c>='0' && c<='9') {
698 par[npar]=10*par[npar]+c-'0';
699 break;
700 } else state=ESgotpars;
// ESgotpars״̬��ʾ�����Ѿ����յ�һ�������Ŀ������С���ʱ���ǿ��Ը��ݱ�״̬���յ���
// ��β�ַ�����Ӧ�������н��д����������ڴ���֮ǰ�����������ESsquare ״̬�յ���'?'��
// ˵������������ն��豸˽�����С����ں˲�֧�ֶ��������еĴ�������������ֱ�ӻָ���
// ESnormal ״̬�������ȥִ����Ӧ�������С������д������Ͱ�״̬�ָ��� ESnormal��
701 case ESgotpars:
702 state = ESnormal;
703 if (ques)
704 { ques =0;
705 break;
706 }
707 switch(c) {
// ���c���ַ�'G'��'`'����par[]�е�1�����������кš����кŲ�Ϊ�㣬�������1��
708 case 'G': case '`': // CSI Pn G -���ˮƽ�ƶ���
709 if (par[0]) par[0]--;
710 gotoxy(currcons,par[0],y);
711 break;
// ���c��'A'�����1����������������Ƶ�������������Ϊ0������1�С�
712 case 'A': // CSI Pn A - ������ơ�
713 if (!par[0]) par[0]++;
714 gotoxy(currcons,x,y-par[0]);
715 break;
// ���c��'B'��'e'�����1����������������Ƶ�������������Ϊ0������1�С�
716 case 'B': case 'e': // CSI Pn B - ������ơ�
717 if (!par[0]) par[0]++;
718 gotoxy(currcons,x,y+par[0]);
719 break;
// ���c��'C'��'a'�����1����������������Ƶĸ�����������Ϊ0������1��
720 case 'C': case 'a': // CSI Pn C - ������ơ�
721 if (!par[0]) par[0]++;
722 gotoxy(currcons,x+par[0],y);
723 break;
// ���c��'D'�����1����������������Ƶĸ�����������Ϊ0������1��
724 case 'D': // CSI Pn D - ������ơ�
725 if (!par[0]) par[0]++;
726 gotoxy(currcons,x-par[0],y);
727 break;
// ���c��'E'�����1������������������ƶ������������ص�0�С�������Ϊ0������1�С�
728 case 'E': // CSI Pn E - ������ƻ�0�С�
729 if (!par[0]) par[0]++;
730 gotoxy(currcons,0,y+par[0]);
731 break;
// ���c��'F'�����1������������������ƶ������������ص�0�С�������Ϊ0������1�С�
732 case 'F': // CSI Pn F - ������ƻ�0�С�
733 if (!par[0]) par[0]++;
734 gotoxy(currcons,0,y-par[0]);
735 break;
// ���c��'d'�����1������������������ڵ��кţ���0��������
736 case 'd': // CSI Pn d - �ڵ�ǰ������λ�á�
737 if (par[0]) par[0]--;
738 gotoxy(currcons,x,par[0]);
739 break;
// ���c��'H'��'f'�����1��������������Ƶ����кţ���2��������������Ƶ����кš�
740 case 'H': case 'f': // CSI Pn H - ��궨λ��
741 if (par[0]) par[0]--;
742 if (par[1]) par[1]--;
743 gotoxy(currcons,par[1],par[0]);
744 break;
// ����ַ�c��'J'�����1�����������Թ������λ�������ķ�ʽ��
// ���У�'ESC [ Ps J'��Ps=0 ɾ����굽��Ļ�ˣ�1 ɾ����Ļ��ʼ����괦��2 ����ɾ������
745 case 'J': // CSI Pn J - ��Ļ�����ַ���
746 csi_J(currcons,par[0]);
747 break;
// ����ַ�c��'K'�����һ�����������Թ������λ�ö������ַ�����ɾ�������ķ�ʽ��
// ת�����У�'ESC [ Ps K'��Ps = 0 ɾ������β��1 �ӿ�ʼɾ����2 ���ж�ɾ������
748 case 'K': // CSI Pn K - ���ڲ����ַ���
749 csi_K(currcons,par[0]);
750 break;
// ����ַ�c��'L'����ʾ�ڹ��λ�ô�����n�У��������� 'ESC [ Pn L'����
751 case 'L': // CSI Pn L - ������
752 csi_L(currcons,par[0]);
753 break;
// ����ַ�c��'M'����ʾ�ڹ��λ�ô�ɾ��n�У��������� 'ESC [ Pn M'����
754 case 'M': // CSI Pn M - ɾ���С�
755 csi_M(currcons,par[0]);
756 break;
// ����ַ�c��'P'����ʾ�ڹ��λ�ô�ɾ��n���ַ����������� 'ESC [ Pn P'����
757 case 'P': // CSI Pn P - ɾ���ַ���
758 csi_P(currcons,par[0]);
759 break;
// ����ַ�c��'@'����ʾ�ڹ��λ�ô�����n���ַ����������� 'ESC [ Pn @' ����
760 case '@': // CSI Pn @ - �����ַ���
761 csi_at(currcons,par[0]);
762 break;
// ����ַ�c��'m'����ʾ�ı��괦�ַ�����ʾ���ԣ�����Ӵ֡����»��ߡ���˸�����Եȡ�
// ת�����У�'ESC [ Pn m'��n=0 ������ʾ��1 �Ӵ֣�4 ���»��ߣ�7 ���ԣ�27 ������ʾ�ȡ�
763 case 'm': // CSI Ps m - ������ʾ�ַ����ԡ�
764 csi_m(currcons);
765 break;
// ����ַ�c��'r'�����ʾ�������������ù�������ʼ�кź���ֹ�кš�
766 case 'r': // CSI Pn;Pn r - ���ù������½硣
767 if (par[0]) par[0]--;
768 if (!par[1]) par[1] = video_num_lines;
769 if (par[0] < par[1] &&
770 par[1] <= video_num_lines) {
771 top=par[0];
772 bottom=par[1];
773 }
774 break;
// ����ַ�c��'s'�����ʾ���浱ǰ�������λ�á�
775 case 's': // CSI s - ������λ�á�
776 save_cur(currcons);
777 break;
// ����ַ�c��'u'�����ʾ�ָ���굽ԭ�����λ�ô���
778 case 'u': // CSI u - �ָ�����Ĺ��λ�á�
779 restore_cur(currcons);
780 break;
// ����ַ�c��'l'��'b'����ֱ��ʾ������Ļ�������ʱ������ô����ַ���ʾ����ʱ������
// ����par[1]��par[2]������ֵ�����Ƿֱ����Ϊpar[1]= par[0]+13��par[2]= par[0]+17��
// ����������£����c���ַ�'l'����ôpar[0]���ǿ�ʼ����ʱ˵�ӳٵķ����������c��
// �ַ�'b'����ôpar[0]�������õĴ����ַ�����ֵ��
781 case 'l': /* blank interval */
782 case 'b': /* bold attribute */
783 if (!((npar >= 2) &&
784 ((par[1]-13) == par[0]) &&
785 ((par[2]-17) == par[0])))
786 break;
787 if ((c=='l')&&(par[0]>=0)&&(par[0]<=60))
788 {
789 blankinterval = HZ*60*par[0];
790 blankcount = blankinterval;
791 }
792 if (c=='b')
793 vc_cons[currcons].vc_bold_attr
794 = par[0];
795 }
796 break;
// ״̬ESfunckey��ʾ���ǽ��յ��˼����Ϲ��ܼ�������һ�����С����Dz�����ʾ�����ǻָ���
// ����״̬ESnormal��
797 case ESfunckey: // ���̹��ܼ��롣
798 state = ESnormal;
799 break;
// ״̬ESsetterm��ʾ�����豸�����ַ�������״̬��DCS������ʱ���յ��ַ� 'S'����ָ���
// ʼ����ʾ�ַ����ԡ����յ����ַ���'L'��'l'��������ر�������ʾ��ʽ��
800 case ESsetterm: /* Setterm functions. */
801 state = ESnormal;
802 if (c == 'S') {
803 def_attr = attr;
804 video_erase_char = (video_erase_char&0x0ff) |
(def_attr<<8);
805 } else if (c == 'L')
806 ; /*linewrap on*/
807 else if (c == 'l')
808 ; /*linewrap off*/
809 break;
// ״̬ESsetgraph��ʾ�յ������ַ���ת������'ESC (' �� 'ESC )'�����Ƿֱ�����ָ��G0��
// G1���õ��ַ�������ʱ���յ��ַ�'0'����ѡ��ͼ���ַ�����ΪG0��G1�����յ����ַ���'B'��
// ��ѡ����ͨASCII�ַ�����ΪG0��G1���ַ�����
810 case ESsetgraph: // 'CSI ( 0'��'CSI ( B' - ѡ���ַ�����
811 state = ESnormal;
812 if (c == '0')
813 translate = GRAF_TRANS;
814 else if (c == 'B')
815 translate = NORM_TRANS;
816 break;
817 default:
818 state = ESnormal;
819 }
820 }
821 set_cursor(currcons); // �������������õĹ��λ�ã�������ʾ�������й��λ�á�
822 }
824 /*
825 * void con_init(void);
826 *
827 * This routine initalizes console interrupts, and does nothing
828 * else. If you want the screen to clear, call tty_write with
829 * the appropriate escape-sequece.
830 *
831 * Reads the information preserved by setup.s to determine the current display
832 * type and sets everything accordingly.
833 */
/*
* void con_init(void);
*
* ����ӳ����ʼ������̨�жϣ�����ʲô�������������������Ļ�ɾ��Ļ�����ʹ��
* �ʵ���ת���ַ����е���tty_write()������
*
* ��ȡsetup.s�������Ϣ������ȷ����ǰ��ʾ�����ͣ���������������ز�����
*/
834 void con_init(void)
835 {
836 register unsigned char a;
837 char *display_desc = "????";
838 char *display_ptr;
839 int currcons = 0; // ��ǰ�������̨�š�
840 long base, term;
841 long video_memory;
// ���ȸ���setup.s����ȡ�õ�ϵͳӲ�����������������60--68�У���ʼ������������ר��
// �ľ�̬ȫ�ֱ�����
843 video_num_columns = ORIG_VIDEO_COLS; // ��ʾ����ʾ�ַ�������
844 video_size_row = video_num_columns * 2; // ÿ���ַ���ʹ�õ��ֽ�����
845 video_num_lines = ORIG_VIDEO_LINES; // ��ʾ����ʾ�ַ�������
846 video_page = ORIG_VIDEO_PAGE; // ��ǰ��ʾҳ�档
847 video_erase_char = 0x0720; // �����ַ���0x20���ַ���0x07���ԣ���
848 blankcount = blankinterval; // Ĭ�ϵĺ������ʱ�䣨���������
// Ȼ�������ʾģʽ�ǵ�ɫ���Dz�ɫ�ֱ�������ʹ�õ���ʾ�ڴ���ʼλ���Լ���ʾ�Ĵ�������
// �˿ںź���ʾ�Ĵ������ݶ˿ںš������õ�BIOS��ʾ��ʽ����7�����ʾ�ǵ�ɫ��ʾ����
850 if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */
851 {
852 video_mem_base = 0xb0000; // ���õ���ӳ���ڴ���ʼ��ַ��
853 video_port_reg = 0x3b4; // ���õ��������Ĵ����˿ڡ�
854 video_port_val = 0x3b5; // ���õ������ݼĴ����˿ڡ�
// �������Ǹ���BIOS�ж�int 0x10����0x12��õ���ʾģʽ��Ϣ���ж���ʾ���ǵ�ɫ��ʾ��
// ���Dz�ɫ��ʾ������ʹ�������жϹ������õ���BX�Ĵ�������ֵ������0x10����˵����EGA
// ������˳�ʼ��ʾ����Ϊ EGA��ɫ����Ȼ EGA �����н϶���ʾ�ڴ棬���ڵ�ɫ��ʽ�����ֻ
// �����õ�ַ��Χ��0xb0000--0xb8000֮�����ʾ�ڴ档Ȼ������ʾ�������ַ���Ϊ'EGAm'��
// ������ϵͳ��ʼ���ڼ���ʾ�������ַ�������ʾ����Ļ�����Ͻǡ�
// ע�⣬����ʹ����bx�ڵ����ж�int 0x10ǰ���Ƿı�ķ������жϿ������͡���BL��
// �жϵ��ú�ֵ���ı䣬��ʾ��ʾ��֧��Ah=12h���ܵ��ã���EGA����Ƴ�����VGA�����͵�
// ��ʾ�������жϵ��÷���ֵδ�䣬��ʾ��ʾ����֧��������ܣ���˵����һ�㵥ɫ��ʾ����
855 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
856 {
857 video_type = VIDEO_TYPE_EGAM; // ������ʾ���ͣ�EGA��ɫ����
858 video_mem_term = 0xb8000; // ������ʾ�ڴ�ĩ�˵�ַ��
859 display_desc = "EGAm"; // ������ʾ�����ַ�����
860 }
// ���BX�Ĵ�����ֵ����0x10����˵���ǵ�ɫ��ʾ��MDA������8KB��ʾ�ڴ档
861 else
862 {
863 video_type = VIDEO_TYPE_MDA; // ������ʾ����(MDA��ɫ)��
864 video_mem_term = 0xb2000; // ������ʾ�ڴ�ĩ�˵�ַ��
865 display_desc = "*MDA"; // ������ʾ�����ַ�����
866 }
867 }
// �����ʾ��ʽ��Ϊ7��˵���Dz�ɫ��ʾ������ʱ�ı���ʽ��������ʾ�ڴ���ʼ��ַΪ0xb8000��
// ��ʾ���������Ĵ����˿ڵ�ַΪ 0x3d4�����ݼĴ����˿ڵ�ַΪ 0x3d5��
868 else /* If not, it is color. */
869 {
870 can_do_colour = 1; // ���ò�ɫ��ʾ��־��
871 video_mem_base = 0xb8000; // ��ʾ�ڴ���ʼ��ַ��
872 video_port_reg = 0x3d4; // ���ò�ɫ��ʾ�����Ĵ����˿ڡ�
873 video_port_val = 0x3d5; // ���ò�ɫ��ʾ���ݼĴ����˿ڡ�
// ���ж���ʾ��������BX������0x10����˵����EGA��ʾ������ʱ����32KB��ʾ�ڴ����
// ��0xb8000-0xc0000��������˵����CGA��ʾ����ֻ��ʹ��8KB��ʾ�ڴ棨0xb8000-0xba000����
874 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
875 {
876 video_type = VIDEO_TYPE_EGAC; // ������ʾ���ͣ�EGA��ɫ����
877 video_mem_term = 0xc0000; // ������ʾ�ڴ�ĩ�˵�ַ��
878 display_desc = "EGAc"; // ������ʾ�����ַ�����
879 }
880 else
881 {
882 video_type = VIDEO_TYPE_CGA; // ������ʾ���ͣ�CGA����
883 video_mem_term = 0xba000; // ������ʾ�ڴ�ĩ�˵�ַ��
884 display_desc = "*CGA"; // ������ʾ�����ַ�����
885 }
886 }
// �������������㵱ǰ��ʾ���ڴ��Ͽ��Կ�����������̨������Ӳ������������������̨��
// ����������ʾ�ڴ���video_memory����ÿ���������̨ռ�õ��ֽ�����ÿ���������̨ռ�õ�
// ��ʾ�ڴ���������Ļ��ʾ���� video_num_lines ����ÿ���ַ�ռ�е��ֽ���video_size_row��
// ���Ӳ������������������̨��������ϵͳ�����������MAX_CONSOLES���Ͱ��������̨
// ��������ΪMAX_CONSOLES����������������������̨����Ϊ0��������Ϊ1�������ܰɣ�����
// �������ʾ�ڴ��������жϳ����������̨�����õ�ÿ���������̨ռ����ʾ�ڴ��ֽ�����
887 video_memory = video_mem_term - video_mem_base;
888 NR_CONSOLES = video_memory / (video_num_lines * video_size_row);
889 if (NR_CONSOLES > MAX_CONSOLES) // MAX_CONSOLES = 8��
890 NR_CONSOLES = MAX_CONSOLES;
891 if (!NR_CONSOLES)
892 NR_CONSOLES = 1;
893 video_memory /= NR_CONSOLES; // ÿ���������̨ռ����ʾ�ڴ��ֽ�����
895 /* Let the user known what kind of display driver we are using */
/* ��ʼ�����ڹ����ı�������Ҫ����EGA/VGA�� */
// Ȼ����������Ļ�����Ͻ���ʾ�����ַ��������õķ�����ֱ�ӽ��ַ���д����ʾ�ڴ����Ӧ
// λ�ô������Ƚ���ʾָ��display_ptrָ����Ļ��1���Ҷ˲�4���ַ�����ÿ���ַ���2��
// �ֽڣ���˼�8����Ȼ��ѭ�������ַ������ַ�������ÿ����1���ַ����տ�1�������ֽڡ�
897 display_ptr = ((char *)video_mem_base) + video_size_row - 8;
898 while (*display_desc)
899 {
900 *display_ptr++ = *display_desc++;
901 display_ptr++;
902 }
904 /* Initialize the variables used for scrolling (mostly EGA/VGA) */
/* ��ʼ�����ڹ����ı���(��Ҫ����EGA/VGA) */
// ע�⣬��ʱ��ǰ�������̨��currcons�ѱ���ʼ��λ0���������ʵ�����dz�ʼ��0�������
// ��̨�Ľṹvc_cons[0]�е������ֶ�ֵ�����磬�������origin��ǰ���115�����ѱ�����Ϊ
// vc_cons[0].vc_origin��������������0�ſ���̨��Ĭ�Ϲ�����ʼ�ڴ�λ�� video_mem_start
// ��Ĭ�Ϲ���ĩ���ڴ�λ�ã�ʵ��������Ҳ����0�ſ���̨ռ�õIJ�����ʾ�ڴ�����Ȼ���ʼ
// ����0���������̨���������Ժͱ�־ֵ��
906 base = origin = video_mem_start = video_mem_base; // Ĭ�Ϲ�����ʼ�ڴ�λ�á�
907 term = video_mem_end = base + video_memory; // 0����Ļ�ڴ�ĩ��λ�á�
908 scr_end = video_mem_start + video_num_lines * video_size_row; // ����ĩ��λ�á�
909 top = 0; // ��ʼ���ù���ʱ�����кź͵����кš�
910 bottom = video_num_lines;
911 attr = 0x07; // ��ʼ������ʾ�ַ����ԣ��ڵװ��֣���
912 def_attr = 0x07; // ����Ĭ����ʾ�ַ����ԡ�
913 restate = state = ESnormal; // ��ʼ��ת�����в����ĵ�ǰ����һ״̬��
914 checkin = 0;
915 ques = 0; // �յ��ʺ��ַ���־��
916 iscolor = 0; // ��ɫ��ʾ��־��
917 translate = NORM_TRANS; // ʹ�õ��ַ�������ͨASCII�������
918 vc_cons[0].vc_bold_attr = -1; // �����ַ����Ա�־��-1��ʾ���ã���
// ��������0�ſ���̨��ǰ�������λ�ú���Ӧ���ڴ�λ��pos������ѭ����������ļ�
// ���������̨�ṹ�IJ���ֵ�����˸���ռ�õ���ʾ�ڴ濪ʼ�ͽ���λ�ò�ͬ�����ǵij�ʼֵ��
// ���϶���0�ſ���̨��ͬ��
920 gotoxy(currcons,ORIG_X,ORIG_Y);
921 for (currcons = 1; currcons<NR_CONSOLES; currcons++) {
922 vc_cons[currcons] = vc_cons[0]; // ����0�Žṹ�IJ�����
923 origin = video_mem_start = (base += video_memory);
924 scr_end = origin + video_num_lines * video_size_row;
925 video_mem_end = (term += video_memory);
926 gotoxy(currcons,0,0); // ��궼��ʼ������Ļ���Ͻ�λ�á�
927 }
// ������õ�ǰǰ̨����̨����Ļԭ�㣨���Ͻǣ�λ�ú���ʾ�������й����ʾλ�ã������ü�
// ���ж�0x21��������������&keyboard_interrupt�Ǽ����жϴ������̵�ַ����Ȼ��ȡ���ж�
// ����оƬ8259A �жԼ����жϵ����Σ�������Ӧ���̷����� IRQ1 �����źš����λ���̿�
// �������������̿�ʼ����������
928 update_screen(); // ����ǰ̨ԭ������ù��λ�á�
929 set_trap_gate(0x21,&keyboard_interrupt); // �μ�system.h����36�п�ʼ��
930 outb_p(inb_p(0x21)&0xfd,0x21); // ȡ���Լ����жϵ����Σ�����IRQ1��
931 a=inb_p(0x61); // ��ȡ���̶˿�0x61��8255A�˿�PB����
932 outb_p(a|0x80,0x61); // ���ý�ֹ���̹�����λ7��λ����
933 outb_p(a,0x61); // ���������̹��������Ը�λ���̡�
934 }
// ���µ�ǰǰ̨����̨��
// ��ǰ̨����̨ת��Ϊfg_consoleָ�����������̨��fg_console�����õ�ǰ̨�������̨�š�
936 void update_screen(void)
937 {
938 set_origin(fg_console); // ���ù�����ʼ��ʾ�ڴ��ַ��
939 set_cursor(fg_console); // ������ʾ�������й����ʾ�ڴ�λ�á�
940 }
942 /* from bsd-net-2: */
//// ֹͣ������
// ��λ8255A PB�˿ڵ�λ1��λ0���μ�kernel/sched.c�����Ķ�ʱ�����˵����
944 void sysbeepstop(void)
945 {
946 /* disable counter 2 */ /* ��ֹ��ʱ��2 */
947 outb(inb_p(0x61)&0xFC, 0x61);
948 }
950 int beepcount = 0; // ����ʱ����઼�����
// ��ͨ������
// 8255AоƬPB�˿ڵ�λ1�����������Ŀ����źţ�λ0����8253��ʱ��2�����źţ��ö�ʱ
// �������������������������Ϊ������������Ƶ�ʡ����Ҫʹ��������������Ҫ���������ȿ�
// �� PB�˿ڣ�0x61��λ1�� λ0����λ����Ȼ�����ö�ʱ��2ͨ������һ���Ķ�ʱƵ�ʼ��ɡ�
// �μ�boot/setup.s�����8259AоƬ��̷�����kernel/sched.c�����Ķ�ʱ�����˵����
952 static void sysbeep(void)
953 {
954 /* enable counter 2 */ /* ������ʱ��2 */
955 outb_p(inb_p(0x61)|3, 0x61);
956 /* set command for counter 2, 2 byte write */ /* �����ö�ʱ��2���� */
957 outb_p(0xB6, 0x43); // ��ʱ��оƬ�����ּĴ����˿ڡ�
958 /* send 0x637 for 750 HZ */ /* ����Ƶ��Ϊ750HZ������Ͷ�ʱֵ0x637 */
959 outb_p(0x37, 0x42); // ͨ��2���ݶ˿ڷֱ��ͼ����ߵ��ֽڡ�
960 outb(0x06, 0x42);
961 /* 1/8 second */ /* ����ʱ��Ϊ1/8�� */
962 beepcount = HZ/8;
963 }
//// ��������
// ����Ļ���ݸ��Ƶ�����ָ�����û�������arg�С�
// ����arg��������;��һ�����ڴ��ݿ���̨�ţ�������Ϊ�û�������ָ�롣
965 int do_screendump(int arg)
966 {
967 char *sptr, *buf = (char *)arg;
968 int currcons, l;
// ����������֤�û��ṩ�Ļ�����������������������ʵ���չ��Ȼ����俪ʼ��ȡ������̨
// ��currcons�����жϿ���̨����Ч֮�ͰѸÿ���̨��Ļ�������ڴ����ݸ��Ƶ��û�����
// ����
970 verify_area(buf,video_num_columns*video_num_lines);
971 currcons = get_fs_byte(buf);
972 if ((currcons<1) || (currcons>NR_CONSOLES))
973 return -EIO;
974 currcons--;
975 sptr = (char *) origin;
976 for (l=video_num_lines*video_num_columns; l>0 ; l--)
977 put_fs_byte(*sptr++,buf++);
978 return(0);
979 }
// ����������
// ���û���blankIntervalʱ������û�а��κΰ���ʱ������Ļ�������Ա�����Ļ��
981 void blank_screen()
982 {
983 if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
984 return;
985 /* blank here. I can't find out how to do it, though */
986 }
// �ָ���������Ļ��
// ���û������κΰ���ʱ���ͻָ����ں���״̬����Ļ��ʾ���ݡ�
988 void unblank_screen()
989 {
990 if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
991 return;
992 /* unblank here */
993 }
//// ����̨��ʾ������
// �ú����������ں���ʾ����printk()��kernel/printk.c���������ڵ�ǰǰ̨����̨����ʾ
// �ں���Ϣ������������ѭ��ȡ���������е��ַ����������ַ������Կ��ƹ���ƶ���ֱ����
// ʾ����Ļ�ϡ�
// ���� b��null��β���ַ���������ָ�롣
995 void console_print(const char * b)
996 {
997 int currcons = fg_console;
998 char c;
// ѭ����ȡ������b�е��ַ��������ǰ�ַ�c�ǻ��з�����Թ��ִ�лس����в�����Ȼ��
// ȥ������һ���ַ�������ǻس�������ֱ��ִ�лس�������Ȼ��ȥ������һ���ַ���
1000 while (c = *(b++)) {
1001 if (c == 10) {
1002 cr(currcons);
1003 lf(currcons);
1004 continue;
1005 }
1006 if (c == 13) {
1007 cr(currcons);
1008 continue;
1009 }
// �ڶ�ȡ��һ�����ǻس������ַ���������ֵ�ǰ�����λ��x�Ѿ�������Ļ��ĩ�ˣ�����
// ����۷�����һ�п�ʼ����Ȼ����ַ��ŵ����������ʾ�ڴ�λ�ô���������Ļ����ʾ������
// �ٰѹ������һ��λ�ã�Ϊ��ʾ��һ���ַ�������
1010 if (x>=video_num_columns) {
1011 x -= video_num_columns;
1012 pos -= video_size_row;
1013 lf(currcons);
1014 }
// �Ĵ���al������Ҫ��ʾ���ַ�������������ֽڷŵ�ah�У�Ȼ���ax���ݴ洢������ڴ�
// λ��pos�������ڹ�괦��ʾ�ַ���
1015 __asm__("movb %2,%%ah\n\t" // �����ֽڷŵ�ah�С�
1016 "movw %%ax,%1\n\t" // ax���ݷŵ�pos����
1017 ::"a" (c),
1018 "m" (*(short *)pos),
1019 "m" (attr)
1020 :"ax");
1021 pos += 2;
1022 x++;
1023 }
1024 set_cursor(currcons); // ������õĹ���ڴ�λ�ã�������ʾ�������й��λ�á�
1025 }
1 /*
2 * linux/kernel/serial.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * serial.c
9 *
10 * This module implements the rs232 io functions
11 * void rs_write(struct tty_struct * queue);
12 * void rs_init(void);
13 * and all interrupts pertaining to serial IO.
14 */
/*
* serial.c
* �ó�������ʵ��rs232�������������
* void rs_write(struct tty_struct *queue);
* void rs_init(void);
* �Լ��봮��IO�й�ϵ�������жϴ�������
*/
15
16 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
17 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
18 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
19 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
20
21 #define WAKEUP_CHARS (TTY_BUF_SIZE/4) // ��д�����к���WAKEUP_CHARS���ַ�ʱ�Ϳ�ʼ���͡�
22
23 extern void rs1_interrupt(void); // ���п�1���жϴ�������rs_io.s, 34�У���
24 extern void rs2_interrupt(void); // ���п�2���жϴ�������rs_io.s, 38�У���
25
//// ��ʼ�����ж˿�
// ����ָ�����ж˿ڵĴ��䲨���ʣ�2400bps������������д���ּĴ���������������ж�Դ��
// ���⣬�����2�ֽڵIJ���������ʱ��������������·���ƼĴ�����DLABλ��λ7����
// ������port�Ǵ��ж˿ڻ���ַ������1 - 0x3F8������2 - 0x2F8��
26 static void init(int port)
27 {
28 outb_p(0x80,port+3); /* set DLAB of line control reg */
29 outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */
30 outb_p(0x00,port+1); /* MS of divisor */
31 outb_p(0x03,port+3); /* reset DLAB */
32 outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */
33 outb_p(0x0d,port+1); /* enable all intrs but writes */
34 (void)inb(port); /* read data port to reset things (?) */
35 }
36
//// ��ʼ�������жϳ���ʹ��нӿڡ�
// �ж���������IDT�е������������ú�set_intr_gate()��include/asm/system.h��ʵ�֡�
37 void rs_init(void)
38 {
// �����������������������пڵ��ж�����������rs1_interrupt�Ǵ���1���жϴ�������ָ�롣
// ����1ʹ�õ��ж���int 0x24������2����int 0x23���μ���2-2��system.h�ļ���
39 set_intr_gate(0x24,rs1_interrupt); // ���ô��п�1���ж�������(IRQ4�ź�)��
40 set_intr_gate(0x23,rs2_interrupt); // ���ô��п�2���ж�������(IRQ3�ź�)��
41 init(tty_table[64].read_q->data); // ��ʼ�����п�1(.data�Ƕ˿ڻ���ַ)��
42 init(tty_table[65].read_q->data); // ��ʼ�����п�2��
43 outb(inb_p(0x21)&0xE7,0x21); // ������8259A��ӦIRQ3��IRQ4�ж�����
44 }
45
46 /*
47 * This routine gets called when tty_write has put something into
48 * the write_queue. It must check wheter the queue is empty, and
49 * set the interrupt register accordingly
50 *
51 * void _rs_write(struct tty_struct * tty);
52 */
/*
* ��tty_write()�ѽ����ݷ������(д)����ʱ�����������ӳ����ڸ�
* �ӳ����б������ȼ��д�����Ƿ�Ϊ�գ�Ȼ��������Ӧ�жϼĴ�����
*/
//// �������ݷ��������
// �ú���ʵ����ֻ�ǿ������ͱ��ּĴ����ѿ��жϱ�־���˺��ͱ��ּĴ�����ʱ��UART�ͻ�
// �����ж������ڸô����жϴ��������У������ȡ��д����βָ�봦���ַ������������
// �ͱ��ּĴ����С�һ��UART�Ѹ��ַ������˳�ȥ�����ͱ��ּĴ����ֻ��ն������ж�����
// ����ֻҪд�����л����ַ���ϵͳ�ͻ��ظ�����������̣����ַ�һ��һ���ط��ͳ�ȥ����д
// �����������ַ��������˳�ȥ��д���б���ˣ��жϴ�������ͻ���ж������Ĵ����еķ���
// ���ּĴ����ж�������־��λ�����Ӷ��ٴν�ֹ���ͱ��ּĴ����������ж����˴Ρ�ѭ����
// ���Ͳ���Ҳ��֮������
53 void rs_write(struct tty_struct * tty)
54 {
// ���д���в��գ������ȴ�0x3f9����0x2f9����ȡ�ж������Ĵ������ݣ����Ϸ��ͱ��ּĴ���
// �ж�������־��λ1������д�ظüĴ����������������ͱ��ּĴ�����ʱUART���ܹ�������
// ��������͵��ַ��������жϡ�write_q.data���Ǵ��ж˿ڻ���ַ��
55 cli();
56 if (!EMPTY(tty->write_q))
57 outb(inb_p(tty->write_q->data+1)|0x02,tty->write_q->data+1);
58 sti();
59 }
60
1 /*
2 * linux/kernel/rs_io.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * rs_io.s
9 *
10 * This module implements the rs232 io interrupts.
11 */
/*
* ��ģ��ʵ��rs232��������жϴ�������
*/
12
13 .text
14 .globl _rs1_interrupt,_rs2_interrupt
15
// size�Ƕ�д���л��������ֽڳ��ȡ���ֵ������2�Ĵη������ұ�����tty_io.c�е�ƥ�䡣
16 size = 1024 /* must be power of two !
17 and must match the value
18 in tty_io.c!!! */
19
20 /* these are the offsets into the read/write buffer structures */
/* ������Щ�Ƕ�д������нṹ�е�ƫ���� */
// ��Ӧ include/linux/tty.h �ļ��� tty_queue �ṹ�и��ֶε��ֽ�ƫ����������rs_addr
// ��Ӧtty_queue�ṹ��data�ֶΡ����ڴ����ն˻�����У����ֶδ���Ŵ��ж˿ڻ���ַ��
21 rs_addr = 0 // ���ж˿ں��ֶ�ƫ�ƣ��˿���0x3f8��0x2f8����
22 head = 4 // ��������ͷָ���ֶ�ƫ�ơ�
23 tail = 8 // ��������βָ���ֶ�ƫ�ơ�
24 proc_list = 12 // �ȴ��û���Ľ����ֶ�ƫ�ơ�
25 buf = 16 // �������ֶ�ƫ�ơ�
26
// ��һ��д������������ں˾ͻ��Ҫ��д�������ַ��Ľ�������Ϊ�ȴ�״̬����д�������
// �л�ʣ�����256���ַ�ʱ���жϴ�������Ϳ��Ի�����Щ�ȴ����̼�����д�����з��ַ���
27 startup = 256 /* chars left in write queue when we restart it */
/* ���������¿�ʼдʱ����������ʣ���ַ�������*/
28
29 /*
30 * These are the actual interrupt routines. They look where
31 * the interrupt is coming from, and take appropriate action.
32 */
/*
* ��Щ��ʵ�ʵ��жϴ������������ȼ���жϵ���Դ��Ȼ��ִ��
* ��Ӧ�Ĵ�����
*/
//// ���ж˿�1�жϴ���������ڵ㡣
// ��ʼ��ʱrs1_interrupt��ַ�������ж�������0x24�У���Ӧ8259A���ж�����IRQ4���š�
// �������Ȱ�tty���д����ն�1������1����д�������ָ��ĵ�ַ��ջ��tty_io.c��81����
// Ȼ����ת��rs_int���������������������ô���1�ʹ���2�Ĵ������빫�á��ַ��������
// �ṹtty_queue��ʽ��μ�include/linux/tty.h����22�С�
33 .align 2
34 _rs1_interrupt:
35 pushl $_table_list+8 // tty���д���1��д�������ָ���ַ��ջ��
36 jmp rs_int
37 .align 2
//// ���ж˿�2�жϴ���������ڵ㡣
38 _rs2_interrupt:
39 pushl $_table_list+16 // tty���д���2��д�������ָ���ַ��ջ��
// ��δ��������öμĴ���ds��esָ���ں����ݶΣ�Ȼ��Ӷ�Ӧ��д�������data�ֶ�ȡ��
// ���ж˿ڻ���ַ���õ�ַ��2�����жϱ�ʶ�Ĵ���IIR�Ķ˿ڵ�ַ����λ0 = 0����ʾ����
// Ҫ�������жϡ����Ǹ���λ2��λ1ʹ��ָ����ת��������Ӧ�ж�Դ���ʹ����ӳ�����ÿ
// ���ӳ����л��ڴ������λUART ����Ӧ�ж�Դ�����ӳ��غ���δ����ѭ���ж���
// ���������ж�Դ��λ0 = 0��������������жϻ��������ж�Դ����IIR��λ0��Ȼ��0��
// �����жϴ���������ٵ�����Ӧ�ж�Դ�ӳ������������ֱ�����𱾴��жϵ������ж�Դ��
// ����������λ����ʱUART���Զ�������IIR��λ0 =1����ʾ�����������жϣ������ж�
// ���������˳���
40 rs_int:
41 pushl %edx
42 pushl %ecx
43 pushl %ebx
44 pushl %eax
45 push %es
46 push %ds /* as this is an interrupt, we cannot */
47 pushl $0x10 /* know that bs is ok. Load it */
48 pop %ds /* ��������һ���жϳ������Dz�֪��ds�Ƿ���ȷ��*/
49 pushl $0x10 /* ���Լ������ǣ���ds��esָ���ں����ݶΣ� */
50 pop %es
51 movl 24(%esp),%edx // ȡ����35��39����ջ����Ӧ���ڻ������ָ���ַ��
52 movl (%edx),%edx // ȡ��������нṹָ�루��ַ����edx��
53 movl rs_addr(%edx),%edx // ȡ����1����2���˿ڻ���ַ��edx��
54 addl $2,%edx /* interrupt ident. reg */ /* ָ���жϱ�ʶ�Ĵ��� */
// �жϱ�ʶ�Ĵ����˿ڵ�ַ��0x3fa��0x2fa����
55 rep_int:
56 xorl %eax,%eax
57 inb %dx,%al // ȡ�жϱ�ʶ�ֽڣ����ж��ж���Դ����4���ж��������
58 testb $1,%al // �����ж����������жϣ�λ0 = 0���жϣ���
59 jne end // ���������жϣ�����ת���˳�������end��
60 cmpb $6,%al /* this shouldn't happen, but ... */ /*�ⲻ�ᷢ��������*/
61 ja end // alֵ����6������ת��end��û������״̬����
62 movl 24(%esp),%ecx // �����ӳ���֮ǰ�ѻ������ָ���ַ����ecx��
63 pushl %edx // ��ʱ�����жϱ�ʶ�Ĵ����˿ڵ�ַ��
64 subl $2,%edx // edx�лָ����ڻ���ֵַ0x3f8��0x2f8����
65 call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */
// ���������ָ�����д������ж�ʱ��al��λ0=0��λ2��λ1���ж����ͣ�����൱���Ѿ���
// �ж����ͳ���2�������ٳ�2�������ת������79�У���Ӧ���ж����͵�ַ������ת������ȥ
// ����Ӧ�������ж���Դ��4�֣�modem״̬�����仯��Ҫд�����ͣ��ַ���Ҫ�������գ��ַ���
// ��·״̬�����仯�����������ַ��ж�ͨ�����÷��ͱ��ּĴ�����־ʵ�֡���serial.c����
// �У���д���������������ʱ��rs_write()�����ͻ����ж������Ĵ������ݣ������Ϸ��ͱ�
// �ּĴ����ж�������־���Ӷ���ϵͳ��Ҫ�����ַ�ʱ�������жϷ�����
66 popl %edx // �ָ��жϱ�ʶ�Ĵ����˿ڵ�ַ0x3fa����0x2fa����
67 jmp rep_int // ��ת�������ж����������жϲ�����Ӧ������
68 end: movb $0x20,%al // �ж��˳����������жϿ��������ͽ����ж�ָ��EOI��
69 outb %al,$0x20 /* EOI */
70 pop %ds
71 pop %es
72 popl %eax
73 popl %ebx
74 popl %ecx
75 popl %edx
76 addl $4,%esp # jump over _table_list entry # ��������ָ���ַ��
77 iret
78
// ���ж����ʹ����ӳ����ַ��ת��������4���ж���Դ��
// modem״̬�仯�жϣ�д�ַ��жϣ����ַ��жϣ���·״̬�������жϡ�
79 jmp_table:
80 .long modem_status,write_char,read_char,line_status
81
// ����modem״̬�����仯�������˴��жϡ�ͨ����modem״̬�Ĵ���MSR������и�λ������
82 .align 2
83 modem_status:
84 addl $6,%edx /* clear intr by reading modem status reg */
85 inb %dx,%al /* ͨ����modem״̬�Ĵ������и�λ��0x3fe�� */
86 ret
87
// ������·״̬�����仯��������δ����жϡ�ͨ������·״̬�Ĵ���LSR������и�λ������
88 .align 2
89 line_status:
90 addl $5,%edx /* clear intr by reading line status reg. */
91 inb %dx,%al /* ͨ������·״̬�Ĵ������и�λ��0x3fd�� */
92 ret
93
// ����UARTоƬ���յ��ַ�����������жϡ��Խ��ջ���Ĵ���ִ�ж������ɸ�λ���ж�Դ��
// ����ӳ����յ����ַ��ŵ����������read_qͷָ�루head�����������ø�ָ��ǰ��һ
// ���ַ�λ�á���headָ���Ѿ����ﻺ����ĩ�ˣ��������۷�����������ʼ����������C��
// ��do_tty_interrupt()��Ҳ��copy_to_cooked()�����Ѷ�����ַ�������������淶ģʽ��
// ����������������secondary����
94 .align 2
95 read_char:
96 inb %dx,%al // ��ȡ���ջ���Ĵ���RBR���ַ���al��
97 movl %ecx,%edx // ��ǰ���ڻ������ָ���ַ��edx��
98 subl $_table_list,%edx // ��ǰ���ڶ���ָ���ַ - �������ָ�����ַ ��edx��
99 shrl $3,%edx // ��ֵ/8���ô��ںš����ڴ���1��1�����ڴ���2��2��
100 movl (%ecx),%ecx # read-queue // ȡ��������нṹ��ַ��ecx��
101 movl head(%ecx),%ebx // ȡ�������л���ͷָ����ebx��
102 movb %al,buf(%ecx,%ebx) // ���ַ����ڻ�������ͷָ����ָλ�ô���
103 incl %ebx // ��ͷָ��ǰ�ƣ����ƣ�һ�ֽڡ�
104 andl $size-1,%ebx // �û��������ȶ�ͷָ��ȡģ������
105 cmpl tail(%ecx),%ebx // ������ͷָ����βָ��Ƚϡ�
106 je 1f // ��ָ���ƶ�����ȣ���ʾ����������������ͷָ�룬��ת��
107 movl %ebx,head(%ecx) // �����Ĺ���ͷָ�롣
108 1: addl $63,%edx // ���ں�ת����tty�ţ�63��64������Ϊ������ջ��
109 pushl %edx
110 call _do_tty_interrupt // ����tty�жϴ���C������tty_io.c��342�У���
111 addl $4,%esp // ������ջ�����������ء�
112 ret
113
// ���������˷��ͱ��ּĴ��������жϱ�־������˴��жϡ�˵����Ӧ�����ն˵�д�ַ������
// �������ַ���Ҫ���͡����Ǽ����д�����е�ǰ�����ַ��������ַ�����С��256��������
// �ȴ�д�������̡�Ȼ���д�������β��ȡ��һ���ַ����ͣ��������ͱ���βָ�롣���д��
// ������ѿգ�����ת��write_buffer_empty������д������пյ������
114 .align 2
115 write_char:
116 movl 4(%ecx),%ecx # write-queue // ȡд������нṹ��ַ��ecx��
117 movl head(%ecx),%ebx // ȡд����ͷָ����ebx��
118 subl tail(%ecx),%ebx // ͷָ�� - βָ�� = �������ַ�����
119 andl $size-1,%ebx # nr chars in queue
120 je write_buffer_empty // ��ͷָ�� = βָ�룬˵��д���пգ���ת������
121 cmpl $startup,%ebx // �������ַ���������256����
122 ja 1f // ��������ת������
123 movl proc_list(%ecx),%ebx # wake up sleeping process # ���ѵȴ��Ľ��̡�
// ȡ�ȴ��ö��еĽ���ָ�룬���ж��Ƿ�Ϊ�ա�
124 testl %ebx,%ebx # is there any? # �еȴ�д�Ľ�����
125 je 1f // �ǿյģ�����ǰ��ת�����1����
126 movl $0,(%ebx) // ��������Ϊ������״̬�����ѽ��̣���
127 1: movl tail(%ecx),%ebx // ȡβָ�롣
128 movb buf(%ecx,%ebx),%al // �ӻ�����βָ�봦ȡһ�ַ���al��
129 outb %al,%dx // ��˿�0x3f8��0x2f8��д�����ͱ��ּĴ����С�
130 incl %ebx // βָ��ǰ�ơ�
131 andl $size-1,%ebx // βָ������������ĩ�ˣ����ۻء�
132 movl %ebx,tail(%ecx) // �������Ĺ���βָ�롣
133 cmpl head(%ecx),%ebx // βָ����ͷָ��Ƚϣ�
134 je write_buffer_empty // ����ȣ���ʾ�����ѿգ�����ת��
135 ret
// ����д�������write_q�ѿյ���������еȴ�д�ô����ն˵Ľ�������֮��Ȼ�����η�
// �ͱ��ּĴ������жϣ����÷��ͱ��ּĴ�����ʱ�����жϡ�
// �����ʱд�������write_q�ѿգ���ʾ��ǰ���ַ���Ҫ���͡���������Ӧ�����������顣
// ���ȿ�����û�н������ȴ�д���пճ���������оͻ���֮�����⣬��Ϊ����ϵͳ�����ַ�
// ��Ҫ���ͣ����Դ�ʱ����Ҫ��ʱ��ֹ���ͱ��ּĴ���THR��ʱ�����жϡ��������ַ�������
// д���������ʱ��serial.c�е�rs_write()�������ٴ��������ͱ��ּĴ�����ʱ�����жϣ�
// ���UART���ֻᡰ�Զ�������ȡд��������е��ַ��������ͳ�ȥ��
136 .align 2
137 write_buffer_empty:
138 movl proc_list(%ecx),%ebx # wake up sleeping process # ���ѵȴ��Ľ��̡�
// ȡ�ȴ��ö��еĽ��̵�ָ�룬���ж��Ƿ�Ϊ�ա�
139 testl %ebx,%ebx # is there any? # �еȴ��Ľ�����
140 je 1f // �ޣ�����ǰ��ת�����1����
141 movl $0,(%ebx) // ��������Ϊ������״̬�����ѽ��̣���
142 1: incl %edx // ָ��˿�0x3f9��0x2f9����
143 inb %dx,%al // ��ȡ�ж������Ĵ���IER��
144 jmp 1f // �����ӳ١�
145 1: jmp 1f /* ���η��ͱ��ּĴ������жϣ�λ1�� */
146 1: andb $0xd,%al /* disable transmit interrupt */
147 outb %al,%dx // �0x3f9(0x2f9)��
148 ret
1 /*
2 * linux/kernel/tty_io.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
9 * or rs-channels. It also implements echoing, cooked mode etc.
10 *
11 * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
12 */
/*
* 'tty_io.c'��tty�ն�һ�ַ���صĸо������������ǿ���̨���Ǵ����նˡ�
* �ó���ͬ��ʵ���˻��ԡ��淶(��)ģʽ�ȡ�
*
* Kill-line���⣬ҪллJohn T Kohl����ͬʱ�������˵� VMIN = VTIME = 0 ʱ�����⡣
*/
13
14 #include <ctype.h> // �ַ�����ͷ�ļ���������һЩ�й��ַ������жϺ�ת���ĺꡣ
15 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
16 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ�����������ԭ�͡�
17 #include <unistd.h> // unistd.h�DZ����ų����������ļ����������˸��ֺ�����
18
// ������ʱ���棨alarm���ź����ź�λͼ�ж�Ӧ�ı�������λ��
19 #define ALRMMASK (1<<(SIGALRM-1))
20
21 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
22 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
23 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
24 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵ�Ƕ��ʽ���ꡣ
25
// ��ֹ�����飨������鷢���źţ�������pgrpָ��������ţ�sigָ���źţ�privȨ�ޡ�
// ����ָ��������pgrp�е�ÿ�����̷���ָ���ź�sig��ֻҪ��һ�����̷��ͳɹ����ͻ�
// ����0���������û���ҵ�ָ���������pgrp���κ�һ�����̣��س�����-ESRCH����
// �ҵ����������pgrp�Ľ��̣����Ƿ����ź�ʧ�ܣ��ط���ʧ�ܵĴ����롣
26 int kill_pg(int pgrp, int sig, int priv); // kernel/exit.c��171��
// �ж�һ���������Ƿ��ǹ¶����̡����������0���������1��
27 int is_orphaned_pgrp(int pgrp); // kernel/exit.c��232��
28
// ��ȡtermios�ṹ������ģʽ��־��֮һ�����������ж�һ����־���Ƿ�����λ��־��
29 #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f) // ����ģʽ��־��
30 #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f) // ����ģʽ��־��
31 #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) // ���ģʽ��־��
32
// ȡtermios�ṹ�ն����⣨���أ�ģʽ��־���е�һ����־��
33 #define L_CANON(tty) _L_FLAG((tty),ICANON) // ȡ�淶ģʽ��־��
34 #define L_ISIG(tty) _L_FLAG((tty),ISIG) // ȡ�źű�־��
35 #define L_ECHO(tty) _L_FLAG((tty),ECHO) // ȡ�����ַ���־��
36 #define L_ECHOE(tty) _L_FLAG((tty),ECHOE) // �淶ģʽʱȡ���Բ�����־��
37 #define L_ECHOK(tty) _L_FLAG((tty),ECHOK) // �淶ģʽʱȡKILL������ǰ�б�־��
38 #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL) // ȡ���Կ����ַ���־��
39 #define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE) // �淶ģʽʱȡKILL�����в����Ա�־��
40 #define L_TOSTOP(tty) _L_FLAG((tty),TOSTOP) // ���ں�̨�������SIGTTOU�źš�
41
// ȡtermios�ṹ����ģʽ��־���е�һ����־��
42 #define I_UCLC(tty) _I_FLAG((tty),IUCLC) // ȡ��д��Сдת����־��
43 #define I_NLCR(tty) _I_FLAG((tty),INLCR) // ȡ���з�NLת�س���CR��־��
44 #define I_CRNL(tty) _I_FLAG((tty),ICRNL) // ȡ�س���CRת���з�NL��־��
45 #define I_NOCR(tty) _I_FLAG((tty),IGNCR) // ȡ���Իس���CR��־��
46 #define I_IXON(tty) _I_FLAG((tty),IXON) // ȡ�����������־XON��
47
// ȡtermios�ṹ���ģʽ��־���е�һ����־��
48 #define O_POST(tty) _O_FLAG((tty),OPOST) // ȡִ�����������־��
49 #define O_NLCR(tty) _O_FLAG((tty),ONLCR) // ȡ���з�NLת�س����з�CR-NL��־��
50 #define O_CRNL(tty) _O_FLAG((tty),OCRNL) // ȡ�س���CRת���з�NL��־��
51 #define O_NLRET(tty) _O_FLAG((tty),ONLRET) // ȡ���з�NLִ�лس����ܵı�־��
52 #define O_LCUC(tty) _O_FLAG((tty),OLCUC) // ȡСдת��д�ַ���־��
53
// ȡtermios�ṹ���Ʊ�־���в����ʡ�CBAUD�Dz����������루0000017����
54 #define C_SPEED(tty) ((tty)->termios.c_cflag & CBAUD)
// �ж�tty�ն��Ƿ��ѹ��ߣ�hang up�������䴫�䲨�����Ƿ�ΪB0��0����
55 #define C_HUP(tty) (C_SPEED((tty)) == B0)
56
// ȡ��Сֵ�ꡣ
57 #ifndef MIN
58 #define MIN(a,b) ((a) < (b) ? (a) : (b))
59 #endif
60
// ���涨��tty�ն�ʹ�õĻ�����нṹ����tty_queues �� tty�ն˱��ṹ����tty_table��
// QUEUES��tty�ն�ʹ�õĻ���������������α�ն˷��������֣�master��slave����ÿ��
// tty�ն�ʹ��3��tty ������У����Ƿֱ������ڻ�����̻�������Ķ����� read_queue��
// ���ڻ�����Ļ���������д���� write_queue���Լ����ڱ���淶ģʽ�ַ��ĸ����������
// secondary��
61 #define QUEUES (3*(MAX_CONSOLES+NR_SERIALS+2*NR_PTYS)) // ��54�
62 static struct tty_queue tty_queues[QUEUES]; // tty����������顣
63 struct tty_struct tty_table[256]; // tty���ṹ���顣
64
// �����趨�������͵�tty�ն���ʹ�û�����нṹ��tty_queues[]�����е���ʼ��λ�á�
// 8���������̨�ն�ռ��tty_queues[]���鿪ͷ24�3 X MAX_CONSOLES����0 -- 23����
// ���������ն�ռ������6�3 X NR_SERIALS����24 -- 29����
// 4����α�ն�ռ������12�3 X NR_PTYS����30 -- 41����
// 4����α�ն�ռ������12�3 X NR_PTYS����42 -- 53����
65 #define con_queues tty_queues
66 #define rs_queues ((3*MAX_CONSOLES) + tty_queues)
67 #define mpty_queues ((3*(MAX_CONSOLES+NR_SERIALS)) + tty_queues)
68 #define spty_queues ((3*(MAX_CONSOLES+NR_SERIALS+NR_PTYS)) + tty_queues)
69
// �����趨��������tty�ն���ʹ�õ�tty�ṹ��tty_table[]�����е���ʼ��λ�á�
// 8���������̨�ն˿���tty_table[]���鿪ͷ64�0 -- 63����
// ���������ն�ʹ������2�64 -- 65����
// 4����α�ն�ʹ�ô�128��ʼ������64�128 -- 191����
// 4����α�ն�ʹ�ô�192��ʼ������64�192 -- 255����
70 #define con_table tty_table // �������̨�ն�tty�����ų�����
71 #define rs_table (64+tty_table) // �����ն�tty����
72 #define mpty_table (128+tty_table) // ��α�ն�tty����
73 #define spty_table (192+tty_table) // ��α�ն�tty����
74
75 int fg_console = 0; // ��ǰǰ̨����̨�ţ���Χ0--7����
76
77 /*
78 * these are the tables used by the machine code handlers.
79 * you can implement virtual consoles.
80 */
/*
* �����ǻ�������ʹ�õĻ�����нṹ��ַ����ͨ�����������
* �����ʵ���������̨��
*/
// tty��д������нṹ��ַ������rs_io.s����ʹ�ã�����ȡ�ö�д������нṹ�ĵ�ַ��
81 struct tty_queue * table_list[]={
82 con_queues + 0, con_queues + 1, // ǰ̨����̨����д���нṹ��ַ��
83 rs_queues + 0, rs_queues + 1, // �����ն�1����д���нṹ��ַ��
84 rs_queues + 3, rs_queues + 4 // �����ն�2����д���нṹ��ַ��
85 };
86
//// �ı�ǰ̨����̨��
// ��ǰ̨����̨�趨Ϊָ�����������̨��
// ������new_console - ָ�����¿���̨�š�
87 void change_console(unsigned int new_console)
88 {
// �������ָ���Ŀ���̨�Ѿ���ǰ̨���߲�����Ч�����˳����������õ�ǰǰ̨����̨�ţ�ͬ
// ʱ����table_list[]�е�ǰ̨����̨����д���нṹ��ַ�������µ�ǰǰ̨����̨��Ļ��
89 if (new_console == fg_console || new_console >= NR_CONSOLES)
90 return;
91 fg_console = new_console;
92 table_list[0] = con_queues + 0 + fg_console*3;
93 table_list[1] = con_queues + 1 + fg_console*3;
94 update_screen(); // kernel/chr_drv/console.c��936��
95 }
96
//// ������л����������ý��̽�����ж�˯��״̬��
// ������queue - ָ�����е�ָ�롣
// ������ȡ���л��������ַ�֮ǰ��Ҫ���ô˺���������֤�������ǰ����û���ź�Ҫ������
// ����ָ���Ķ��л������գ����ý��̽�����ж�˯��״̬�����ö��еĽ��̵ȴ�ָ��ָ��
// �ý��̡�
97 static void sleep_if_empty(struct tty_queue * queue)
98 {
99 cli();
100 while (!(current->signal & ~current->blocked) && EMPTY(queue))
101 interruptible_sleep_on(&queue->proc_list);
102 sti();
103 }
104
//// �����л����������ý��̽�����жϵ�˯��״̬��
// ������queue - ָ�����е�ָ�롣
// �����������л�������д���ַ�֮ǰ��Ҫ���ô˺����ж϶��������
105 static void sleep_if_full(struct tty_queue * queue)
106 {
// ������л������������˳�������������û���ź���Ҫ���������Ҷ��л������п���ʣ
// �������� < 128�����ý��̽�����ж�˯��״̬�����øö��еĽ��̵ȴ�ָ��ָ��ý��̡�
107 if (!FULL(queue))
108 return;
109 cli();
110 while (!(current->signal & ~current->blocked) && LEFT(queue)<128)
111 interruptible_sleep_on(&queue->proc_list);
112 sti();
113 }
114
//// �ȴ�������
// ���ǰ̨����̨�����л������գ����ý��̽�����ж�˯��״̬��
115 void wait_for_keypress(void)
116 {
117 sleep_if_empty(tty_table[fg_console].secondary);
118 }
119
//// ���Ƴɹ淶ģʽ�ַ����С�
// �����ն�termios�ṹ�����õĸ��ֱ�־����ָ��tty�ն˶����л������е��ַ�����ת��
// �ɹ淶ģʽ����ģʽ���ַ�������ڸ������У��淶ģʽ���У��С�
// ������tty - ָ���ն˵�tty�ṹָ�롣
120 void copy_to_cooked(struct tty_struct * tty)
121 {
122 signed char c;
123
// ���ȼ�鵱ǰ�ն�tty�ṹ�л������ָ���Ƿ���Ч�������������ָ�붼��NULL����˵��
// �ں�tty��ʼ�����������⡣
124 if (!(tty->read_q || tty->write_q || tty->secondary)) {
125 printk("copy_to_cooked: missing queues\n\r");
126 return;
127 }
// �������Ǹ����ն�termios�ṹ�е�����ͱ��ر�־���Դ�tty�����л�������ȡ����ÿ��
// �ַ������ʵ��Ĵ�����Ȼ����븨������secondary�С�������ѭ�����У������ʱ������
// �������Ѿ�ȡ�ջ��߸������л������Ѿ������ַ������˳�ѭ���塣�������ʹӶ����л�
// ����βָ�봦ȡһ�ַ�������βָ��ǰ��һ���ַ�λ�á�Ȼ����ݸ��ַ�����ֵ���д�����
// ���⣬���������_POSIX_VDISABLE��\0������ô�ڶ��ַ����������ң����ַ�����ֵ����
// _POSIX_VDISABLE��ֵʱ����ʾ��ֹʹ����Ӧ��������ַ��Ĺ��ܡ�
128 while (1) {
129 if (EMPTY(tty->read_q))
130 break;
131 if (FULL(tty->secondary))
132 break;
133 GETCH(tty->read_q,c); // ȡһ�ַ���c����ǰ��βָ�롣
// ������ַ��ǻس���CR��13������ô���س�ת���б�־CRNL��λ�����ַ�ת��Ϊ���з�
// NL��10��������������Իس���־NOCR��λ������Ը��ַ����������������ַ��������
// ���ǻ��з�NL��10�������һ���ת�س���־NLCR��λ������ת��Ϊ�س���CR��13����
134 if (c==13) {
135 if (I_CRNL(tty))
136 c=10;
137 else if (I_NOCR(tty))
138 continue;
139 } else if (c==10 && I_NLCR(tty))
140 c=13;
// �����дתСд�����־UCLC��λ�����ַ�ת��ΪСд�ַ���
141 if (I_UCLC(tty))
142 c=tolower(c);
// �������ģʽ��־���й淶ģʽ��־CANON ����λ����Զ�ȡ���ַ��������´����� ���ȣ�
// ������ַ��Ǽ�����ֹ�����ַ�KILL(^U)�����������ĵ�ǰ��ִ��ɾ��������ɾ��һ����
// ����ѭ���������ǣ���� tty�������в��գ�����ȡ���ĸ������������һ���ַ����ǻ���
// ��NL��10�������Ҹ��ַ������ļ������ַ���^D������ѭ��ִ�����д��룺
// ������ػ��Ա�־ECHO ��λ����ô�����ַ��ǿ����ַ���ֵ < 32��������ttyд�����з�
// ����������ַ�ERASE��^H����Ȼ���ٷ���һ�������ַ�ERASE�����ҵ��ø�ttyд��������
// д�����е������ַ�������ն���Ļ�ϡ� ���⣬��Ϊ�����ַ��ڷ���д����ʱ��Ҫ��2����
// �ڱ�ʾ������^V�������Ҫ���ر�Կ����ַ������һ��ERASE�����tty��������ͷָ��
// ����1�ֽڡ����⣬���������_POSIX_VDISABLE��\0������ô�ڶ��ַ����������ң����ַ�
// ����ֵ���� _POSIX_VDISABLE��ֵʱ����ʾ��ֹʹ����Ӧ��������ַ��Ĺ��ܡ�
143 if (L_CANON(tty)) {
144 if ((KILL_CHAR(tty) != _POSIX_VDISABLE) &&
145 (c==KILL_CHAR(tty))) {
146 /* deal with killing the input line */
147 while(!(EMPTY(tty->secondary) ||
148 (c=LAST(tty->secondary))==10 ||
149 ((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
150 (c==EOF_CHAR(tty))))) {
151 if (L_ECHO(tty)) { // �����ػ��Ա�־��λ��
152 if (c<32) // �����ַ�Ҫɾ2�ֽڡ�
153 PUTCH(127,tty->write_q);
154 PUTCH(127,tty->write_q);
155 tty->write(tty);
156 }
157 DEC(tty->secondary->head);
158 }
159 continue; // ������ȡ���������ַ����д�����
160 }
// ������ַ���ɾ�������ַ�ERASE��^H������ô�����tty�ĸ�������Ϊ�գ����������һ��
// �ַ��ǻ��з�NL(10)���������ļ�����������������������ַ���������ػ��Ա�־ECHO��
// λ����ô�����ַ��ǿ����ַ���ֵ< 32��������tty��д�����з�������ַ�ERASE���ٷ���
// һ�������ַ�ERASE�����ҵ��ø�tty��д���������tty��������ͷָ�����1�ֽڣ���
// �����������ַ���ͬ���أ����������_POSIX_VDISABLE��\0������ô�ڶ��ַ����������ң�
// ���ַ�����ֵ���� _POSIX_VDISABLE ��ֵʱ����ʾ��ֹʹ����Ӧ��������ַ��Ĺ��ܡ�
161 if ((ERASE_CHAR(tty) != _POSIX_VDISABLE) &&
162 (c==ERASE_CHAR(tty))) {
163 if (EMPTY(tty->secondary) ||
164 (c=LAST(tty->secondary))==10 ||
165 ((EOF_CHAR(tty) != _POSIX_VDISABLE) &&
166 (c==EOF_CHAR(tty))))
167 continue;
168 if (L_ECHO(tty)) { // �����ػ��Ա�־��λ��
169 if (c<32)
170 PUTCH(127,tty->write_q);
171 PUTCH(127,tty->write_q);
172 tty->write(tty);
173 }
174 DEC(tty->secondary->head);
175 continue;
176 }
177 }
// ���������IXON��־����ʹ�ն�ֹͣ/��ʼ��������ַ������á����û�����ô˱�־����
// ôֹͣ�Ϳ�ʼ�ַ�������Ϊһ���ַ������̶�ȡ������δ����У������ȡ���ַ���ֹͣ��
// ��STOP��^S��������tty ֹͣ��־����tty ��ͣ�����ͬʱ��������������ַ���������
// ���������У������������������ַ�������ַ��ǿ�ʼ�ַ�START��^Q������λttyֹͣ
// ��־���ָ�tty�����ͬʱ�����ÿ����ַ������������������ַ���
// ���ڿ���̨��˵�������tty->write()��console.c�е�con_write()��������˿���̨��
// ���ڷ���stopped=1����������ͣ����Ļ����ʾ���ַ���chr_drv/console.c����586�У���
// ����α�ն�Ҳ�������������ն�stopped��־������ͣд������chr_drv/pty.c����24�У���
// ���ڴ����նˣ�ҲӦ���ڷ����ն˹����и����ն�stopped��־��ͣ���ͣ�������δʵ�֡�
178 if (I_IXON(tty)) {
179 if ((STOP_CHAR(tty) != _POSIX_VDISABLE) &&
180 (c==STOP_CHAR(tty))) {
181 tty->stopped=1;
182 tty->write(tty);
183 continue;
184 }
185 if ((START_CHAR(tty) != _POSIX_VDISABLE) &&
186 (c==START_CHAR(tty))) {
187 tty->stopped=0;
188 tty->write(tty);
189 continue;
190 }
191 }
// ������ģʽ��־����ISIG��־��λ����ʾ�ն˼��̿��Բ����źţ������յ������ַ�INTR��
// QUIT��SUSP �� DSUSP ʱ����ҪΪ���̲�����Ӧ���źš� ������ַ��Ǽ����жϷ���^C����
// ����ǰ����֮�����������н��̷��ͼ����ж��ź�SIGINT��������������һ�ַ��� �����
// �ַ����˳�����^\��������ǰ����֮�����������н��̷��ͼ����˳��ź�SIGQUIT��������
// ������һ�ַ�������ַ�����ͣ����^Z��������ǰ���̷�����ͣ�ź�SIGTSTP��ͬ��������
// ����_POSIX_VDISABLE��\0������ô�ڶ��ַ����������ң����ַ�����ֵ����_POSIX_VDISABLE
// ��ֵʱ����ʾ��ֹʹ����Ӧ��������ַ��Ĺ��ܡ����²��ن����� :-)
192 if (L_ISIG(tty)) {
193 if ((INTR_CHAR(tty) != _POSIX_VDISABLE) &&
194 (c==INTR_CHAR(tty))) {
195 kill_pg(tty->pgrp, SIGINT, 1);
196 continue;
197 }
198 if ((QUIT_CHAR(tty) != _POSIX_VDISABLE) &&
199 (c==QUIT_CHAR(tty))) {
200 kill_pg(tty->pgrp, SIGQUIT, 1);
201 continue;
202 }
203 if ((SUSPEND_CHAR(tty) != _POSIX_VDISABLE) &&
204 (c==SUSPEND_CHAR(tty))) {
205 if (!is_orphaned_pgrp(tty->pgrp))
206 kill_pg(tty->pgrp, SIGTSTP, 1);
207 continue;
208 }
209 }
// ������ַ��ǻ��з�NL��10�����������ļ�������EOF��4��^D������ʾһ���ַ��Ѵ����꣬
// ��Ѹ�����������е�ǰ�����ַ�����ֵsecondary.data��1������ں���tty_read()��ȡ
// ��һ���ַ�����ֵ���ᱻ��1���μ�315�С�
210 if (c==10 || (EOF_CHAR(tty) != _POSIX_VDISABLE &&
211 c==EOF_CHAR(tty)))
212 tty->secondary->data++;
// �������ģʽ��־���л��Ա�־ECHO����λ״̬����ô������ַ��ǻ��з�NL��10������
// ���з�NL��10���ͻس���CR��13������ttyд���л������У�����ַ��ǿ����ַ���ֵ<32��
// ���һ��Կ����ַ���־ECHOCTL��λ�����ַ�'^'���ַ� c+64 ����ttyд�����У�Ҳ����
// ��ʾ^C��^H��)�������ַ�ֱ�ӷ���ttyд��������С������ø�ttyд����������
213 if (L_ECHO(tty)) {
214 if (c==10) {
215 PUTCH(10,tty->write_q);
216 PUTCH(13,tty->write_q);
217 } else if (c<32) {
218 if (L_ECHOCTL(tty)) {
219 PUTCH('^',tty->write_q);
220 PUTCH(c+64,tty->write_q);
221 }
222 } else
223 PUTCH(c,tty->write_q);
224 tty->write(tty);
225 }
// ÿһ��ѭ��ĩ�����������ַ����븨�������С�
226 PUTCH(c,tty->secondary);
227 }
// ������˳�ѭ������ѵȴ��ø���������еĽ��̣�����еĻ�����
228 wake_up(&tty->secondary->proc_list);
229 }
230
231 /*
232 * Called when we need to send a SIGTTIN or SIGTTOU to our process
233 * group
234 *
235 * We only request that a system call be restarted if there was if the
236 * default signal handler is being used. The reason for this is that if
237 * a job is catching SIGTTIN or SIGTTOU, the signal handler may not want
238 * the system call to be restarted blindly. If there is no way to reset the
239 * terminal pgrp back to the current pgrp (perhaps because the controlling
240 * tty has been released on logout), we don't want to be in an infinite loop
241 * while restarting the system call, and have it always generate a SIGTTIN
242 * or SIGTTOU. The default signal handler will cause the process to stop
243 * thus avoiding the infinite loop problem. Presumably the job-control
244 * cognizant parent will fix things up before continuging its child process.
245 */
/* ����Ҫ�����ź�SIGTTIN �� SIGTTOU �����ǽ����������н���ʱ�ͻ���øú�����
*
* �ڽ���ʹ��Ĭ���źŴ����������£����ǽ�Ҫ��һ��ϵͳ���ñ��������������
* ��ϵͳ�������źŶ����жϡ���������ԭ���ǣ����һ����ҵ���ڲ���SIGTTIN
* �� SIGTTOU�źţ���ô��Ӧ�źž��������ϣ��ϵͳ���ñ�äĿ���������������
* û�������������ն˵�pgrp��λ����ǰpgrp���������������logoutʱ�����ն�
* �ѱ��ͷţ�����ô���Dz���ϣ������������ϵͳ����ʱ����һ������ѭ���У�����
* ���Dz��� SIGTTIN �� SIGTTOU �źš�Ĭ�ϵ��źž����ʹ�ý���ֹͣ���������
* ��������ѭ�����⡣��������ʶ����ҵ���Ƶĸ����̻��ڼ���ִ�����ӽ���֮ǰ
* ������㶨��
*/
//// ��ʹ���ն˵Ľ����������н��̷����źš�
// �ں�̨�������е�һ�����̷��ʿ����ն�ʱ���ú����������̨�������е����н��̷���
// SIGTTIN��SIGTTOU�źš����ۺ�̨�������еĽ����Ƿ��Ѿ���������Ե����������źţ�
// ��ǰ���̶��������˳���д���������ء�
246 int tty_signal(int sig, struct tty_struct *tty)
247 {
// ���Dz�ϣ��ֹͣһ���¶��������еĽ��̣��μ��ļ�kernel/exit.c�е�232���ϵ�˵������
// ��������ǰ�������ǹ¶������飬�ͳ������ء��������ǰ���������н��̷���ָ����
// ��sig��
248 if (is_orphaned_pgrp(current->pgrp))
249 return -EIO; /* don't stop an orphaned pgrp */
250 (void) kill_pg(current->pgrp,sig,1); // �����ź�sig��
// �������źű���ǰ�������������Σ������߱���ǰ���̺��Ե�����������ء��������
// ��ǰ���̶��ź�sig�������µĴ����������ô�ͷ������ǿɱ��жϵ���Ϣ������ͷ�����
// ϵͳ����������������Լ���ִ�е���Ϣ��
251 if ((current->blocked & (1<<(sig-1))) ||
252 ((int) current->sigaction[sig-1].sa_handler == 1))
253 return -EIO; /* Our signal will be ignored */
254 else if (current->sigaction[sig-1].sa_handler)
255 return -EINTR; /* We _will_ be interrupted :-) */
256 else
257 return -ERESTARTSYS; /* We _will_ be interrupted :-) */
258 /* (but restart after we continue) */
259 }
260
//// tty��������
// ���ն˸�����������ж�ȡָ���������ַ����ŵ��û�ָ���Ļ������С�
// ������channel - ���豸�ţ�buf �C �û�������ָ�룻nr - �����ֽ�����
// �����Ѷ��ֽ�����
261 int tty_read(unsigned channel, char * buf, int nr)
262 {
263 struct tty_struct * tty;
264 struct tty_struct * other_tty = NULL;
265 char c, * b=buf;
266 int minimum,time;
267
// �����жϲ�����Ч�Բ�ȡ�ն˵�tty�ṹָ�롣���tty�ն˵������������ָ�붼��NULL��
// ��EIO������Ϣ�����tty�ն���һ��α�նˣ�����ȡ����һ����Ӧα�ն˵�tty�ṹ
// other_tty��
268 if (channel > 255)
269 return -EIO;
270 tty = TTY_TABLE(channel);
271 if (!(tty->write_q || tty->read_q || tty->secondary))
272 return -EIO;
// �����ǰ����ʹ�õ����������ڴ�����tty�նˣ������ն˵Ľ������ȴ�뵱ǰ������Ų�
// ͬ����ʾ��ǰ�����Ǻ�̨�������е�һ�����̣������̲���ǰ̨����������Ҫֹͣ��ǰ����
// ������н��̡�����������Ҫ��ǰ�����鷢��SIGTTIN�źţ������صȴ���Ϊǰ̨����
// �����ִ�ж�������
273 if ((current->tty == channel) && (tty->pgrp != current->pgrp))
274 return(tty_signal(SIGTTIN, tty));
// �����ǰ�ն���α�նˣ���ô��Ӧ����һ��α�ն˾���other_tty��������tty����α�նˣ�
// ��ôother_tty���Ƕ�Ӧ�Ĵ�α�նˣ���֮ҲȻ��
275 if (channel & 0x80)
276 other_tty = tty_table + (channel ^ 0x40);
// Ȼ����� VTIME ��VMIN ��Ӧ�Ŀ����ַ�����ֵ���ö��ַ�������ʱ��ʱֵtime��������
// Ҫ��ȡ���ַ�����minimum���ڷǹ淶ģʽ�£��������dz�ʱ��ʱֵ��VMIN��ʾΪ�������
// ��������Ҫ��ȡ�������ַ�������VTIME��һ��1/10�������ʱֵ��
277 time = 10L*tty->termios.c_cc[VTIME]; // ���ö�������ʱ��ʱֵ��
278 minimum = tty->termios.c_cc[VMIN]; // ������Ҫ��ȡ���ַ�������
// ���tty�ն˴��ڹ淶ģʽ����������СҪ��ȡ�ַ���minimum ���ڽ��������ַ���nr��ͬ
// ʱ�ѽ��̶�ȡnr�ַ��ij�ʱʱ��ֵ����Ϊ����ֵ�����ᳬʱ��������˵���ն˴��ڷǹ淶ģ
// ʽ�£�����ʱ���������ٶ�ȡ�ַ���minimum��������ʱ���ý��Ƕ���ʱ��ʱֵΪ������
// �ý����ȶ�ȡ���������������ַ�������������ַ������� minimum �Ļ��������������
// ָ���ij�ʱֵtime �����ý��̵Ķ���ʱֵ timeout������ȴ���ȡ�����ַ����μ�328�С�
// ����ʱû���������ٶ�ȡ�ַ���minimum��Ϊ0������������Ϊ���������ַ���nr��������
// �������˳�ʱ��ʱֵtime�Ļ����Ͱѽ��̶��ַ���ʱ��ʱֵtimeout����Ϊϵͳ��ǰʱ��ֵ
// + ָ���ij�ʱֵtime��ͬʱ��λtime�� ���⣬����������õ����ٶ�ȡ�ַ���minimum��
// �ڽ�������ȡ���ַ���nr������minimum=nr�������ڹ淶ģʽ�µĶ�ȡ������������VTIME
// ��VMIN��Ӧ�����ַ�ֵ��Լ���Ϳ��ƣ����ǽ��ڷǹ淶ģʽ����ģʽ�������������á�
279 if (L_CANON(tty)) {
280 minimum = nr;
281 current->timeout = 0xffffffff;
282 time = 0;
283 } else if (minimum)
284 current->timeout = 0xffffffff;
285 else {
286 minimum = nr;
287 if (time)
288 current->timeout = time + jiffies;
289 time = 0;
290 }
291 if (minimum>nr)
292 minimum = nr; // ����ȡҪ����ַ�����
// �������ǿ�ʼ�Ӹ���������ѭ��ȡ���ַ����ŵ��û�������buf �С����������ֽ�������0��
// ��ִ������ѭ����������ѭ�������У������ǰ�ն���α�նˣ���ô���Ǿ�ִ�����Ӧ����
// һ��α�ն˵�д��������������һ��α�ն˰��ַ�д�뵱ǰα�ն˸������л������С�����
// ��һ�ն˰�д���л��������ַ����Ƶ���ǰα�ն˶����л������У������й�̺���ת����
// ���뵱ǰα�ն˸��������С�
293 while (nr>0) {
294 if (other_tty)
295 other_tty->write(other_tty);
// ���tty�����������Ϊ�գ����������˹淶ģʽ��־����tty�����л�����δ�������Ҹ�
// ���������ַ�����Ϊ0����ô�����û�����ù����̶��ַ���ʱֵ��Ϊ0�������ߵ�ǰ����
// Ŀǰ�յ��źţ������˳�ѭ���塣����������ն���һ����α�նˣ��������Ӧ����α�ն�
// �Ѿ��Ҷϣ���ô����Ҳ�˳�ѭ���塣�������������������������Ǿ��õ�ǰ���̽������
// ��˯��״̬�����غ�������������ڹ淶ģʽʱ�ں�����Ϊ��λΪ�û��ṩ���ݣ�����ڸ�
// ģʽ�¸��������б���������һ���ַ��ɹ�ȡ�ã���secondary.data������1���С�
296 cli();
297 if (EMPTY(tty->secondary) || (L_CANON(tty) &&
298 !FULL(tty->read_q) && !tty->secondary->data)) {
299 if (!current->timeout ||
300 (current->signal & ~current->blocked)) {
301 sti();
302 break;
303 }
304 if (IS_A_PTY_SLAVE(channel) && C_HUP(other_tty))
305 break;
306 interruptible_sleep_on(&tty->secondary->proc_list);
307 sti();
308 continue;
309 }
310 sti();
// ���濪ʼ��ʽִ��ȡ�ַ�����������ַ���nr���εݼ���ֱ��nr=0���߸����������Ϊ�ա�
// �����ѭ�������У�����ȡ������������ַ�c�����Ұѻ������βָ��tail�����ƶ�һ��
// �ַ�λ�á������ȡ�ַ����ļ���������^D�������ǻ��з�NL��10������Ѹ������������
// �����ַ�����ֵ��1�� ������ַ����ļ���������^D�����ҹ淶ģʽ��־����λ״̬������
// �ϱ�ѭ��������˵�����ڻ�û�������ļ�����������������ԭʼ���ǹ淶��ģʽ��������ģ
// ʽ���û����ַ�����Ϊ��ȡ����Ҳ��ʶ�����еĿ����ַ������ļ��������������ǽ��ַ�
// ֱ�ӷ����û����ݻ����� buf�У����������ַ�����1����ʱ��������ַ�����Ϊ0���ж�
// ѭ�������⣬����ն˴��ڹ淶ģʽ���Ҷ�ȡ���ַ��ǻ��з�NL��10������Ҳ�˳�ѭ����
// ����֮�⣬ֻҪ��û��ȡ�������ַ���nr���Ҹ������в��գ��ͼ���ȡ�����е��ַ���
311 do {
312 GETCH(tty->secondary,c);
313 if ((EOF_CHAR(tty) != _POSIX_VDISABLE &&
314 c==EOF_CHAR(tty)) || c==10)
315 tty->secondary->data--;
316 if ((EOF_CHAR(tty) != _POSIX_VDISABLE &&
317 c==EOF_CHAR(tty)) && L_CANON(tty))
318 break;
319 else {
320 put_fs_byte(c,b++);
321 if (!--nr)
322 break;
323 }
324 if (c==10 && L_CANON(tty))
325 break;
326 } while (nr>0 && !EMPTY(tty->secondary));
// ִ�е��ˣ���ô��� tty �ն˴��ڹ淶ģʽ�£�˵�����ǿ��ܶ����˻��з������������ļ�
// ������������Ǵ��ڷǹ淶ģʽ�£���ô˵�������Ѿ���ȡ��nr���ַ������߸��������Ѿ�
// ��ȡ���ˡ������������Ȼ��ѵȴ������еĽ��̣�Ȼ���Ƿ����ù���ʱ��ʱֵtime����
// ����ʱ��ʱֵtime��Ϊ0�����Ǿ�Ҫ��ȴ�һ����ʱ�����������̿����ַ�д��������С�
// �������ý��̶���ʱ��ʱֵΪϵͳ��ǰʱ��jiffies + ����ʱֵtime����Ȼ������ն˴���
// �淶ģʽ�������Ѿ���ȡ��nr���ַ������ǾͿ���ֱ���˳������ѭ���ˡ�
327 wake_up(&tty->read_q->proc_list);
328 if (time)
329 current->timeout = time+jiffies;
330 if (L_CANON(tty) || b-buf >= minimum)
331 break;
332 }
// ��ʱ��ȡtty�ַ�ѭ��������������˸�λ���̵Ķ�ȡ��ʱ��ʱֵtimeout�������ʱ��ǰ��
// �����յ��źŲ��һ�û�ж�ȡ���κ��ַ���������������ϵͳ���úŷ��ء�����ͷ����Ѷ�ȡ
// ���ַ���(b-buf)��
333 current->timeout = 0;
334 if ((current->signal & ~current->blocked) && !(b-buf))
335 return -ERESTARTSYS;
336 return (b-buf);
337 }
338
//// tty�����
// ���û��������е��ַ�����ttyд���л������С�
// ������channel - ���豸�ţ�buf - ������ָ�룻nr - д�ֽ�����
// ������д�ֽ�����
339 int tty_write(unsigned channel, char * buf, int nr)
340 {
341 static cr_flag=0;
342 struct tty_struct * tty;
343 char c, *b=buf;
344
// �����жϲ�����Ч�Բ�ȡ�ն˵�tty�ṹָ�롣���tty�ն˵������������ָ�붼��NULL��
// ��EIO������Ϣ��
345 if (channel > 255)
346 return -EIO;
347 tty = TTY_TABLE(channel);
348 if (!(tty->write_q || tty->read_q || tty->secondary))
349 return -EIO;
// ������ն˱���ģʽ��־����������TOSTOP����ʾ��̨�������ʱ��Ҫ�����ź�SIGTTOU��
// �����ǰ����ʹ�õ����������ڴ�����tty�նˣ������ն˵Ľ������ȴ�뵱ǰ������Ų�
// ͬ������ʾ��ǰ�����Ǻ�̨�������е�һ�����̣������̲���ǰ̨����������Ҫֹͣ��ǰ��
// ��������н��̡�����������Ҫ��ǰ�����鷢��SIGTTOU�źţ������صȴ���Ϊǰ̨��
// �������ִ��д������
350 if (L_TOSTOP(tty) &&
351 (current->tty == channel) && (tty->pgrp != current->pgrp))
352 return(tty_signal(SIGTTOU, tty));
// �������ǿ�ʼ���û�������buf��ѭ��ȡ���ַ����ŵ�д���л������С�����д�ֽ�������0��
// ��ִ������ѭ����������ѭ�������У������ʱttyд������������ǰ���̽�����жϵ�˯
// ��״̬�������ǰ�������ź�Ҫ���������˳�ѭ���塣
353 while (nr>0) {
354 sleep_if_full(tty->write_q);
355 if (current->signal & ~current->blocked)
356 break;
// ��Ҫд���ַ���nr������0����ttyд���л�������������ѭ��ִ�����²��������ȴ��û�
// ��������ȡ1�ֽڡ�����ն����ģʽ��־���е�ִ�����������־ OPOST ��λ����ִ�ж�
// �ַ��ĺ���������
357 while (nr>0 && !FULL(tty->write_q)) {
358 c=get_fs_byte(b);
359 if (O_POST(tty)) {
// ������ַ��ǻس���'\r'��CR��13�����һس���ת���з���־OCRNL��λ�����ַ�����
// ���з�'\n'��NL��10��������������ַ��ǻ��з�'\n'��NL��10�����һ���ת�س����ܱ�־
// ONLRET��λ�Ļ������ַ����ɻس���'\r'��CR��13����
360 if (c=='\r' && O_CRNL(tty))
361 c='\n';
362 else if (c=='\n' && O_NLRET(tty))
363 c='\r';
// ������ַ��ǻ��з�'\n' ���һس���־cr_flagû����λ��������ת�س�-���б�־ONLCR
// ��λ�Ļ�����cr_flag��־��λ������һ�س�������д�����С�Ȼ�����������һ���ַ���
// ���Сдת��д��־OLCUC��λ�Ļ����ͽ����ַ�ת�ɴ�д�ַ���
364 if (c=='\n' && !cr_flag && O_NLCR(tty)) {
365 cr_flag = 1;
366 PUTCH(13,tty->write_q);
367 continue;
368 }
369 if (O_LCUC(tty)) // Сдת�ɴ�д�ַ���
370 c=toupper(c);
371 }
// ���Ű��û����ݻ���ָ��bǰ��1�ֽڣ���д�ֽ�����1�ֽڣ���λcr_flag��־��������
// �ֽڷ���ttyд�����С�
372 b++; nr--;
373 cr_flag = 0;
374 PUTCH(c,tty->write_q);
375 }
// ��Ҫ����ַ�ȫ��д�꣬����д����������������˳�ѭ������ʱ����ö�Ӧttyд������
// ��д���л������е��ַ���ʾ�ڿ���̨��Ļ�ϣ�����ͨ�����ж˿ڷ��ͳ�ȥ�������ǰ��
// ����tty�ǿ���̨�նˣ���ôtty->write()���õ���con_write()�����tty�Ǵ����նˣ�
// ��tty->write()���õ���rs_write()�������������ֽ�Ҫд����ȴ�д�������ַ�ȡ�ߡ�
// ����������õ��ȳ�����ȥִ����������
376 tty->write(tty);
377 if (nr>0)
378 schedule();
379 }
380 return (b-buf); // ���д����ֽ�����
381 }
382
383 /*
384 * Jeh, sometimes I really like the 386.
385 * This routine is called from an interrupt,
386 * and there should be absolutely no problem
387 * with sleeping even in an interrupt (I hope).
388 * Of course, if somebody proves me wrong, I'll
389 * hate intel for all time :-). We'll have to
390 * be careful and see to reinstating the interrupt
391 * chips before calling this, though.
392 *
393 * I don't think we sleep here under normal circumstances
394 * anyway, which is good, as the task sleeping might be
395 * totally innocent.
396 */
/*
* �ǣ���ʱ����ú�ϲ��386�����ӳ���һ���жϴ���������
* ���ã����Ҽ�ʹ���жϴ���������˯��ҲӦ�þ���û�����⣨��
* ϣ����ˣ�����Ȼ���������֤�����Ǵ��ģ���ô�ҽ�����intel
* һ����J���������DZ���С�ģ��ڵ��ø��ӳ���֮ǰ��Ҫ�ָ��жϡ�
*
* �Ҳ���Ϊ��ͨ�������»ᴦ������˯�ߣ������ܺã���Ϊ����˯��
* ����ȫ����ġ�
*/
//// tty�жϴ������ú��� - �ַ��淶ģʽ������
// ������tty - ָ����tty�ն˺š�
// ��ָ��tty�ն˶��л������е��ַ����ƻ�ת���ɹ淶(��)ģʽ�ַ�������ڸ��������С�
// �ú������ڴ��ڶ��ַ��жϣ�rs_io.s��109���ͼ����жϣ�kerboard.S��69���б����á�
397 void do_tty_interrupt(int tty)
398 {
399 copy_to_cooked(TTY_TABLE(tty));
400 }
401
//// �ַ��豸��ʼ���������գ�Ϊ�Ժ���չ������
402 void chr_dev_init(void)
403 {
404 }
405
//// tty�ն˳�ʼ��������
// ��ʼ�������ն˻�����У���ʼ�������ն˺Ϳ���̨�նˡ�
406 void tty_init(void)
407 {
408 int i;
409
// ���ȳ�ʼ�������ն˵Ļ�����нṹ�����ó�ֵ�����ڴ����ն˵Ķ�/д������У������ǵ�
// data�ֶ�����Ϊ���ж˿ڻ���ֵַ������1��0x3f8������2��0x2f8��Ȼ���ȳ�����������
// �ն˵�tty�ṹ�����������ַ�����c_cc[]���õij�ֵ������include/linux/tty.h�ļ��С�
410 for (i=0 ; i < QUEUES ; i++)
411 tty_queues[i] = (struct tty_queue) {0,0,0,0,""};
412 rs_queues[0] = (struct tty_queue) {0x3f8,0,0,0,""};
413 rs_queues[1] = (struct tty_queue) {0x3f8,0,0,0,""};
414 rs_queues[3] = (struct tty_queue) {0x2f8,0,0,0,""};
415 rs_queues[4] = (struct tty_queue) {0x2f8,0,0,0,""};
416 for (i=0 ; i<256 ; i++) {
417 tty_table[i] = (struct tty_struct) {
418 {0, 0, 0, 0, 0, INIT_C_CC},
419 0, 0, 0, NULL, NULL, NULL, NULL
420 };
421 }
// ���ų�ʼ������̨�նˣ�console.c��834�У����� con_init()�����������Ϊ������Ҫ��
// ����ʾ�����ͺ���ʾ�ڴ�������ȷ��ϵͳ���������̨������NR_CONSOLES����ֵ���������
// �Ŀ���̨tty �ṹ��ʼ��ѭ���С����ڿ���̨��tty �ṹ��425--430����tty�ṹ�а�����
// termios�ṹ�ֶΡ���������ģʽ��־������ʼ��ΪICRNL��־�����ģʽ��־����ʼ��Ϊ��
// �к�����־OPOST�Ͱ�NLת����CRNL�ı�־ONLCR������ģʽ��־������ʼ������IXON��
// ICANON��ECHO��ECHOCTL��ECHOKE��־�������ַ�����c_cc[]�����ú��г�ʼֵINIT_C_CC��
// 435���ϳ�ʼ������̨�ն�tty�ṹ�еĶ����塢д�������������нṹ�����Ƿֱ�ָ��
// tty ������нṹ����tty_table[]�е���Ӧ�ṹ��μ�61--73���ϵ����˵����
422 con_init();
423 for (i = 0 ; i<NR_CONSOLES ; i++) {
424 con_table[i] = (struct tty_struct) {
425 {ICRNL, /* change incoming CR to NL */ /* CRתNL */
426 OPOST|ONLCR, /* change outgoing NL to CRNL */ /*NLתCRNL*/
427 0, // ����ģʽ��־����
428 IXON | ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, // ���ر�־����
429 0, /* console termio */ // ��·��̣�0 -- TTY��
430 INIT_C_CC}, // �����ַ�����c_cc[]��
431 0, /* initial pgrp */ // ������ʼ������pgrp��
432 0, /* initial session */ // ��ʼ�Ự��session��
433 0, /* initial stopped */ // ��ʼֹͣ��־stopped��
434 con_write, // ����̨д������
435 con_queues+0+i*3,con_queues+1+i*3,con_queues+2+i*3
436 };
437 }
// Ȼ���ʼ�������ն˵�tty�ṹ���ֶΡ�450�г�ʼ�������ն�tty �ṹ�еĶ�/д������
// ����нṹ�����Ƿֱ�ָ��tty ������нṹ����tty_table[]�е���Ӧ�ṹ��μ�61--
// 73���ϵ����˵����
438 for (i = 0 ; i<NR_SERIALS ; i++) {
439 rs_table[i] = (struct tty_struct) {
440 {0, /* no translation */ // ����ģʽ��־����0������ת����
441 0, /* no translation */ // ���ģʽ��־����0������ת����
442 B2400 | CS8, // ����ģʽ��־����2400bps��8λ����λ��
443 0, // ����ģʽ��־����
444 0, // ��·��̣�0 -- TTY��
445 INIT_C_CC}, // �����ַ����顣
446 0, // ������ʼ�����顣
447 0, // ��ʼ�Ự�顣
448 0, // ��ʼֹͣ��־��
449 rs_write, // �����ն�д������
450 rs_queues+0+i*3,rs_queues+1+i*3,rs_queues+2+i*3 // ��������
451 };
452 }
// Ȼ���ٳ�ʼ��α�ն�ʹ�õ�tty�ṹ��α�ն������ʹ�õģ���һ������master��α�ն���
// ��һ���ӣ�slave��α�նˡ���˶����Ƕ�Ҫ���г�ʼ�����á���ѭ���У��������ȳ�ʼ��
// ÿ����α�ն˵�tty�ṹ��Ȼ���ٳ�ʼ�����Ӧ�Ĵ�α�ն˵�tty�ṹ��
453 for (i = 0 ; i<NR_PTYS ; i++) {
454 mpty_table[i] = (struct tty_struct) {
455 {0, /* no translation */ // ����ģʽ��־����0������ת����
456 0, /* no translation */ // ���ģʽ��־����0������ת����
457 B9600 | CS8, // ����ģʽ��־����9600bps��8λ����λ��
458 0, // ����ģʽ��־����
459 0, // ��·��̣�0 -- TTY��
460 INIT_C_CC}, // �����ַ����顣
461 0, // ������ʼ�����顣
462 0, // ������ʼ�Ự�顣
463 0, // ��ʼֹͣ��־��
464 mpty_write, // ��α�ն�д������
465 mpty_queues+0+i*3,mpty_queues+1+i*3,mpty_queues+2+i*3
466 };
467 spty_table[i] = (struct tty_struct) {
468 {0, /* no translation */ // ����ģʽ��־����0������ת����
469 0, /* no translation */ // ���ģʽ��־����0������ת����
470 B9600 | CS8, // ����ģʽ��־����9600bps��8λ����λ��
471 IXON | ISIG | ICANON, // ����ģʽ��־����
472 0, // ��·��̣�0 -- TTY��
473 INIT_C_CC}, // �����ַ����顣
474 0, // ������ʼ�����顣
475 0, // ������ʼ�Ự�顣
476 0, // ��ʼֹͣ��־��
477 spty_write, // ��α�ն�д������
478 spty_queues+0+i*3,spty_queues+1+i*3,spty_queues+2+i*3
479 };
480 }
// ����ʼ�������жϴ�������ʹ��нӿ�1��2��serial.c��37�У�������ʾϵͳ���е�����
// ����̨��NR_CONSOLES ��α�ն���NR_PTYS��
481 rs_init();
482 printk("%d virtual consoles\n\r",NR_CONSOLES);
483 printk("%d pty's\n\r",NR_PTYS);
484 }
485
1 /*
2 * linux/kernel/chr_drv/tty_ioctl.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8 #include <termios.h> // �ն������������ͷ�ļ�����Ҫ��������첽ͨ�ſڵ��ն˽ӿڡ�
9
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0�����ݵȡ�
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <linux/tty.h> // ttyͷ�ļ��������й�tty_io������ͨ�ŷ��������������
13
14 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
15 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
16 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
17
// ���ݽ������pgrpȡ�ý����������ĻỰ�š�������kernel/exit.c��161�С�
18 extern int session_of_pgrp(int pgrp);
// ��ʹ��ָ��tty�ն˵Ľ����������н��̷����źš�������chr_drv/tty_io.c��246�С�
19 extern int tty_signal(int sig, struct tty_struct *tty);
20
// ���Dz������������飨���Ϊ�������飩���������벨�������ӵĶ�Ӧ��ϵ�μ��б���˵����
// ���粨������2400bpsʱ����Ӧ��������48��0x30����9600bps��������12��0x1c����
21 static unsigned short quotient[] = {
22 0, 2304, 1536, 1047, 857,
23 768, 576, 384, 192, 96,
24 64, 48, 24, 12, 6, 3
25 };
26
//// �Ĵ��䲨���ʡ�
// ������tty - �ն˶�Ӧ��tty���ݽṹ��
// �ڳ��������־DLAB��λ����£�ͨ���˿�0x3f8��0x3f9��UART�ֱ�д�벨�������ӵ�
// �ֽں��ֽڡ�д����ٸ�λDLABλ�����ڴ���2���������˿ڷֱ���0x2f8��0x2f9��
27 static void change_speed(struct tty_struct * tty)
28 {
29 unsigned short port,quot;
30
// �������ȼ�����tty ָ�����ն��Ƿ��Ǵ����նˣ����������˳������ڴ����ն˵�tty��
// ��������������data �ֶδ���Ŵ��ж˿ڻ�ַ��0x3f8��0x2f8������һ�����̨�ն˵�
// tty�ṹ��read_q.data�ֶ�ֵΪ0��Ȼ����ն�termios�ṹ�Ŀ���ģʽ��־����ȡ������
// �õIJ����������ţ����ݴ˴Ӳ�������������quotient[]��ȡ�ö�Ӧ�IJ���������ֵquot��
// CBAUD�ǿ���ģʽ��־���в�����λ�����롣
31 if (!(port = tty->read_q->data))
32 return;
33 quot = quotient[tty->termios.c_cflag & CBAUD];
// ���ŰѲ���������quotд�봮�ж˿ڶ�ӦUARTоƬ�IJ����������������С���д֮ǰ����
// ��Ҫ����·���ƼĴ��� LCR �ij���������ʱ���λDLAB��λ7����1��Ȼ��� 16λ�IJ���
// �����ӵ��ֽڷֱ�д��˿� 0x3f8��0x3f9 ���ֱ��Ӧ���������ӵ͡����ֽ�����������
// ����ٸ�λLCR��DLAB��־λ��
34 cli();
35 outb_p(0x80,port+3); /* set DLAB */ // �������ó���������־DLAB��
36 outb_p(quot & 0xff,port); /* LS of divisor */ // ������ӵ��ֽڡ�
37 outb_p(quot >> 8,port+1); /* MS of divisor */ // ������Ӹ��ֽڡ�
38 outb(0x03,port+3); /* reset DLAB */ // ��λDLAB��
39 sti();
40 }
41
//// ˢ��tty������С�
// ������queue - ָ���Ļ������ָ�롣
// �����е�ͷָ�����βָ�룬�Ӷ��ﵽ��ջ�������Ŀ�ġ�
42 static void flush(struct tty_queue * queue)
43 {
44 cli();
45 queue->head = queue->tail;
46 sti();
47 }
48
//// �ȴ��ַ����ͳ�ȥ��
49 static void wait_until_sent(struct tty_struct * tty)
50 {
51 /* do nothing - not implemented */ /* ʲô��û�� - ��δʵ�� */
52 }
53
//// ����BREAK���Ʒ���
54 static void send_break(struct tty_struct * tty)
55 {
56 /* do nothing - not implemented */ /* ʲô��û�� - ��δʵ�� */
57 }
58
//// ȡ�ն�termios�ṹ��Ϣ��
// ������tty - ָ���ն˵�tty�ṹָ�룻termios - ���termios�ṹ���û���������
59 static int get_termios(struct tty_struct * tty, struct termios * termios)
60 {
61 int i;
62
// ������֤�û�������ָ����ָ�ڴ��������Ƿ��㹻���粻��������ڴ档Ȼ����ָ���ն�
// ��termios�ṹ��Ϣ���û��������С����0��
63 verify_area(termios, sizeof (*termios)); // kernel/fork.c��24��
64 for (i=0 ; i< (sizeof (*termios)) ; i++)
65 put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );
66 return 0;
67 }
68
//// �����ն�termios�ṹ��Ϣ��
// ������tty - ָ���ն˵�tty�ṹָ�룻termios - �û�������termios�ṹָ�롣
69 static int set_termios(struct tty_struct * tty, struct termios * termios,
70 int channel)
71 {
72 int i, retsig;
73
74 /* If we try to set the state of terminal and we're not in the
75 foreground, send a SIGTTOU. If the signal is blocked or
76 ignored, go ahead and perform the operation. POSIX 7.2) */
/* �����ͼ�����ն˵�״̬����ʱ�ն˲���ǰ̨����ô���Ǿ���Ҫ����
һ��SIGTTOU�źš�������źű��������λ��ߺ����ˣ���ֱ��ִ��
������� POSIX 7.2 */
// �����ǰ����ʹ�õ�tty�ն˵Ľ����������̵Ľ�����Ų�ͬ������ǰ�����ն˲���ǰ̨��
// ��ʾ��ǰ������ͼ�IJ��ܿ��Ƶ��ն˵�termios�ṹ����˸���POSIX����Ҫ��������
// Ҫ����SIGTTOU�ź���ʹ������ն˵Ľ�������ʱִֹͣ�У�������������termios�ṹ��
// ��������źź���tty_signal()����ֵ��ERESTARTSYS��EINTR�����һ����ִ�б��β�����
77 if ((current->tty == channel) && (tty->pgrp != current->pgrp)) {
78 retsig = tty_signal(SIGTTOU, tty); // chr_drv/tty_io.c��246��
79 if (retsig == -ERESTARTSYS || retsig == -EINTR)
80 return retsig;
81 }
// ���Ű��û���������termios�ṹ��Ϣ���Ƶ�ָ���ն�tty�ṹ��termios�ṹ�С���Ϊ��
// ���п����������ն˴��пڴ��䲨���ʣ����������ٸ���termios�ṹ�еĿ���ģʽ��־
// c_cflag�еIJ�������Ϣ�Ĵ���UARTоƬ�ڵĴ��䲨���ʡ����0��
82 for (i=0 ; i< (sizeof (*termios)) ; i++)
83 ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);
84 change_speed(tty);
85 return 0;
86 }
87
//// ��ȡtermio�ṹ�е���Ϣ��
// ������tty - ָ���ն˵�tty�ṹָ�룻termio - ����termio�ṹ��Ϣ���û���������
88 static int get_termio(struct tty_struct * tty, struct termio * termio)
89 {
90 int i;
91 struct termio tmp_termio;
92
// ������֤�û��Ļ�����ָ����ָ�ڴ��������Ƿ��㹻���粻��������ڴ档Ȼ��termios
// �ṹ����Ϣ���Ƶ���ʱ termio �ṹ�С��������ṹ������ͬ�������롢��������ƺͱ���
// ��־���������Ͳ�ͬ��ǰ�ߵ���long�������ߵ���short������ȸ��Ƶ���ʱtermio�ṹ
// ��Ŀ����Ϊ�˽�����������ת����
93 verify_area(termio, sizeof (*termio));
94 tmp_termio.c_iflag = tty->termios.c_iflag;
95 tmp_termio.c_oflag = tty->termios.c_oflag;
96 tmp_termio.c_cflag = tty->termios.c_cflag;
97 tmp_termio.c_lflag = tty->termios.c_lflag;
98 tmp_termio.c_line = tty->termios.c_line;
99 for(i=0 ; i < NCC ; i++)
100 tmp_termio.c_cc[i] = tty->termios.c_cc[i];
// ������ֽڵذ���ʱtermio�ṹ�е���Ϣ���Ƶ��û�termio�ṹ�������С�������0��
101 for (i=0 ; i< (sizeof (*termio)) ; i++)
102 put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );
103 return 0;
104 }
105
106 /*
107 * This only works as the 386 is low-byt-first
108 */
/*
* ����termio���ú����������ڵ��ֽ���ǰ��386 CPU��
*/
//// �����ն�termio�ṹ��Ϣ��
// ������tty - ָ���ն˵�tty�ṹָ�룻termio - �û���������termio�ṹ��
// ���û�������termio����Ϣ���Ƶ��ն˵�termios�ṹ�С�����0 ��
109 static int set_termio(struct tty_struct * tty, struct termio * termio,
110 int channel)
111 {
112 int i, retsig;
113 struct termio tmp_termio;
114
// ��set_termios()һ�����������ʹ�õ��ն˵Ľ����������̵Ľ�����Ų�ͬ������ǰ��
// ���ն˲���ǰ̨����ʾ��ǰ������ͼ�IJ��ܿ��Ƶ��ն˵�termios�ṹ����˸���POSIX
// ����Ҫ��������Ҫ����SIGTTOU�ź���ʹ������ն˵Ľ�������ʱִֹͣ�У�����������
// ��termios�ṹ����������źź���tty_signal()����ֵ��ERESTARTSYS��EINTR�����
// һ����ִ�б��β�����
115 if ((current->tty == channel) && (tty->pgrp != current->pgrp)) {
116 retsig = tty_signal(SIGTTOU, tty);
117 if (retsig == -ERESTARTSYS || retsig == -EINTR)
118 return retsig;
119 }
// ���Ÿ����û���������termio�ṹ��Ϣ����ʱtermio�ṹ�С�Ȼ���ٽ�termio�ṹ����Ϣ
// ���Ƶ�tty�� termios �ṹ�С���������Ŀ����Ϊ�˶�����ģʽ��־�������ͽ���ת������
// �� termio�Ķ���������ת����termios�ij��������͡������ֽṹ��c_line��c_cc[]�ֶ�
// ����ȫ��ͬ�ġ�
120 for (i=0 ; i< (sizeof (*termio)) ; i++)
121 ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
122 *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;
123 *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;
124 *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;
125 *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;
126 tty->termios.c_line = tmp_termio.c_line;
127 for(i=0 ; i < NCC ; i++)
128 tty->termios.c_cc[i] = tmp_termio.c_cc[i];
// �����Ϊ�û��п����������ն˴��пڴ��䲨���ʣ����������ٸ���termios�ṹ�еĿ���
// ģʽ��־c_cflag�еIJ�������Ϣ�Ĵ���UARTоƬ�ڵĴ��䲨���ʣ�������0��
129 change_speed(tty);
130 return 0;
131 }
132
//// tty�ն��豸����������ƺ�����
// ������dev - �豸�ţ�cmd - ioctl���arg - ��������ָ�롣
// �ú������ȸ��ݲ����������豸���ҳ���Ӧ�ն˵�tty�ṹ��Ȼ����ݿ�������cmd�ֱ����
// ������
133 int tty_ioctl(int dev, int cmd, int arg)
134 {
135 struct tty_struct * tty;
136 int pgrp;
137
// ���ȸ����豸��ȡ��tty���豸�ţ��Ӷ�ȡ���ն˵�tty�ṹ�������豸����5�������նˣ���
// ����̵�tty�ֶμ���tty���豸�š���ʱ������̵�tty���豸���Ǹ����������ý���û��
// �����նˣ������ܷ�����ioctl���ã�������ʾ������Ϣ��ͣ����������豸�Ų���5����4��
// ���ǾͿ��Դ��豸����ȡ�����豸�š����豸�ſ�����0������̨�նˣ���1������1�նˣ���
// 2������2�նˣ���
138 if (MAJOR(dev) == 5) {
139 dev=current->tty;
140 if (dev<0)
141 panic("tty_ioctl: dev<0");
142 } else
143 dev=MINOR(dev);
// Ȼ��������豸�ź�tty�������ǿ�ȡ�ö�Ӧ�ն˵�tty�ṹ��������ttyָ���Ӧ���豸
// �ŵ�tty�ṹ��Ȼ���ٸ��ݲ����ṩ��ioctl����cmd���зֱ�����144�к�벿������
// �������豸��dev��tty_table[]����ѡ���Ӧ��tty�ṹ�����dev = 0����ʾ����ʹ��
// ǰ̨�նˣ����ֱ��ʹ���ն˺�fg_console ��Ϊ tty_table[] ������ȡ tty�ṹ�����
// dev����0����ô��Ҫ������������ǣ��� dev �������ն˺ţ��� dev �Ǵ����ն˺Ż���
// α�ն˺š����������ն���tty�ṹ�� tty_table[]���������� dev-1��0 -- 63��������
// ���������նˣ������ǵ� tty�ṹ��������� dev�����磬���dev = 64����ʾ��һ����
// ���ն�1������tty �ṹ���� ttb_table[dev]�� ���dev = 1�����Ӧ�ն˵�tty�ṹ��
// tty_table[0]���μ�tty_io.c�����70 -- 73�С�
144 tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);
145 switch (cmd) {
// ȡ��Ӧ�ն�termios�ṹ��Ϣ����ʱ����arg���û�������ָ�롣
146 case TCGETS:
147 return get_termios(tty,(struct termios *) arg);
// ������termios�ṹ��Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ�����ϣ�����ˢ�£���գ�
// ������С��ٽ���ִ�����������ն�termios�ṹ�IJ�����
148 case TCSETSF:
149 flush(tty->read_q); /* fallthrough */ /* ���ż���ִ�� */
// �������ն�termios����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ����꣨�ľ�����������
// ������Ӱ����������������Ҫʹ��������ʽ��
150 case TCSETSW:
151 wait_until_sent(tty); /* fallthrough */
// ������Ӧ�ն�termios�ṹ��Ϣ����ʱ����arg�DZ���termios�ṹ���û�������ָ�롣
152 case TCSETS:
153 return set_termios(tty,(struct termios *) arg, dev);
// ȡ��Ӧ�ն�termio�ṹ�е���Ϣ����ʱ����arg���û�������ָ�롣
154 case TCGETA:
155 return get_termio(tty,(struct termio *) arg);
// ������termio �ṹ��Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ�����ϣ�����ˢ�£���գ�
// ������С��ٽ���ִ�����������ն�termio �ṹ�IJ�����
156 case TCSETAF:
157 flush(tty->read_q); /* fallthrough */ /* ���ż���ִ�� */
// �������ն�termios����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ����꣨�ľ�����������
// ������Ӱ����������������Ҫʹ��������ʽ��
158 case TCSETAW:
159 wait_until_sent(tty); /* fallthrough */
// ������Ӧ�ն�termio�ṹ��Ϣ����ʱ����arg�DZ���termio�ṹ���û�������ָ�롣
160 case TCSETA:
161 return set_termio(tty,(struct termio *) arg, dev);
// �������argֵ��0����ȴ�������д�����ϣ��գ���������һ��break��
162 case TCSBRK:
163 if (!arg) {
164 wait_until_sent(tty);
165 send_break(tty);
166 }
167 return 0;
// ��ʼ/ֹͣ�����ơ��������arg��TCOOFF��Terminal Control Output OFF��������������
// ����� TCOON����ָ������������ڹ����ָ����ͬʱ��Ҫ��д�����е��ַ��������
// �ӿ��û�������Ӧ�ٶȡ����arg��TCIOFF��Terminal Control Input ON������������룻
// �����TCION�������¿�����������롣
168 case TCXONC:
169 switch (arg) {
170 case TCOOFF:
171 tty->stopped = 1; // ֹͣ�ն������
172 tty->write(tty); // �����������
173 return 0;
174 case TCOON:
175 tty->stopped = 0; // �ָ��ն������
176 tty->write(tty);
177 return 0;
// �������arg��TCIOFF����ʾҪ���ն�ֹͣ���룬�����������ն�д�����з���STOP�ַ���
// ���ն��յ����ַ�ʱ�ͻ���ͣ���롣���������TCION����ʾҪ����һ��START�ַ�������
// �˻ָ����䡣
// STOP_CHAR(tty)����Ϊ ((tty)->termios.c_cc[VSTOP])����ȡ�ն�termios�ṹ�����ַ���
// ���Ӧ��ֵ�����ں˶�����_POSIX_VDISABLE��\0������ô��ijһ��ֵ����_POSIX_VDISABLE
// ��ֵʱ����ʾ��ֹʹ����Ӧ�������ַ����������ֱ���жϸ�ֵ�Ƿ�Ϊ0 ��ȷ��Ҫ��Ҫ��ͣ
// ֹ�����ַ������ն�д�����С�����ͬ��
178 case TCIOFF:
179 if (STOP_CHAR(tty))
180 PUTCH(STOP_CHAR(tty),tty->write_q);
181 return 0;
182 case TCION:
183 if (START_CHAR(tty))
184 PUTCH(START_CHAR(tty),tty->write_q);
185 return 0;
186 }
187 return -EINVAL; /* not implemented */
// ˢ����д�������û�з��͡������յ���û�ж������ݡ��������arg��0����ˢ�£���գ�
// ������У������1����ˢ��������У������2����ˢ�������������С�
188 case TCFLSH:
189 if (arg==0)
190 flush(tty->read_q);
191 else if (arg==1)
192 flush(tty->write_q);
193 else if (arg==2) {
194 flush(tty->read_q);
195 flush(tty->write_q);
196 } else
197 return -EINVAL;
198 return 0;
// �����ն˴�����·ר��ģʽ��
199 case TIOCEXCL:
200 return -EINVAL; /* not implemented */ /* δʵ�� */
// ��λ�ն˴�����·ר��ģʽ��
201 case TIOCNXCL:
202 return -EINVAL; /* not implemented */
// ����ttyΪ�����նˡ���TIOCNOTTY - ��Ҫ�����նˣ���
203 case TIOCSCTTY:
204 return -EINVAL; /* set controlling term NI */ /* δʵ�� */
// ��ȡ�ն˽�����ţ�����ȡǰ̨������ţ��� ������֤�û����������ȣ�Ȼ�����ն�tty
// ��pgrp�ֶε��û�����������ʱ����arg���û�������ָ�롣
205 case TIOCGPGRP: // ʵ�ֿ⺯��tcgetpgrp()��
206 verify_area((void *) arg,4);
207 put_fs_long(tty->pgrp,(unsigned long *) arg);
208 return 0;
// �����ն˽������pgrp��������ǰ̨������ţ��� ��ʱ����arg ���û��������н������
// pgrp ��ָ�롣ִ�и������ǰ�������ǽ��̱����п����նˡ� �����ǰ����û�п����նˣ�
// ����dev ����������նˣ����߿����ն����ڵ�ȷ�����ڴ������ն�dev�������̵ĻỰ��
// ����ն�dev�ĻỰ�Ų�ͬ�������ն˴�����Ϣ��
209 case TIOCSPGRP: // ʵ�ֿ⺯��tcsetpgrp()��
210 if ((current->tty < 0) ||
211 (current->tty != dev) ||
212 (tty->session != current->session))
213 return -ENOTTY;
// Ȼ�����Ǿʹ��û���������ȡ�������õĽ�����ţ����Ը���ŵ���Ч�Խ�����֤�������
// ��pgrpС��0������Ч��Ŵ�����Ϣ����� pgrp�ĻỰ���뵱ǰ���̵IJ�ͬ����
// ���ɴ�����Ϣ���������ǿ��������ն˵Ľ������Ϊprgp����ʱprgp��Ϊǰ̨�����顣
214 pgrp=get_fs_long((unsigned long *) arg);
215 if (pgrp < 0)
216 return -EINVAL;
217 if (session_of_pgrp(pgrp) != current->session)
218 return -EPERM;
219 tty->pgrp = pgrp;
220 return 0;
// ������������л�δ�ͳ����ַ�����������֤�û����������ȣ�Ȼ���ƶ������ַ������û���
// ��ʱ����arg���û�������ָ�롣
221 case TIOCOUTQ:
222 verify_area((void *) arg,4);
223 put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
224 return 0;
// ������������л�δ��ȡ���ַ�����������֤�û����������ȣ�Ȼ���ƶ������ַ������û���
// ��ʱ����arg���û�������ָ�롣
225 case TIOCINQ:
226 verify_area((void *) arg,4);
227 put_fs_long(CHARS(tty->secondary),
228 (unsigned long *) arg);
229 return 0;
// ģ���ն������������������һ��ָ���ַ���ָ����Ϊ��������������ַ������ն��ϼ���ġ�
// �û������ڸÿ����ն��Ͼ��г����û�Ȩ����ж�����Ȩ�ޡ�
230 case TIOCSTI:
231 return -EINVAL; /* not implemented */ /* δʵ�� */
// ��ȡ�ն��豸���ڴ�С��Ϣ���μ�termios.h�е�winsize�ṹ����
232 case TIOCGWINSZ:
233 return -EINVAL; /* not implemented */
// �����ն��豸���ڴ�С��Ϣ���μ�winsize�ṹ����
234 case TIOCSWINSZ:
235 return -EINVAL; /* not implemented */
// ����MODEM״̬�������ߵĵ�ǰ״̬����λ��־�����μ�termios.h��185 -- 196�У���
236 case TIOCMGET:
237 return -EINVAL; /* not implemented */
// ���õ���modem״̬�������ߵ�״̬��true��false����
238 case TIOCMBIS:
239 return -EINVAL; /* not implemented */
// ��λ����MODEM״̬�������ߵ�״̬��
240 case TIOCMBIC:
241 return -EINVAL; /* not implemented */
// ����MODEM״̬���ߵ�״̬�����ijһ����λ��λ����modem��Ӧ��״̬���߽���Ϊ��Ч��
242 case TIOCMSET:
243 return -EINVAL; /* not implemented */
// ��ȡ�����ز�����־��1 - ������0 - �رգ���
244 case TIOCGSOFTCAR:
245 return -EINVAL; /* not implemented */
// ���������ز�����־��1 - ������0 - �رգ���
246 case TIOCSSOFTCAR:
247 return -EINVAL; /* not implemented */
248 default:
249 return -EINVAL;
250 }
251 }
252
1 /*
2 * linux/kernel/math/math_emulate.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * Limited emulation 27.12.91 - mostly loads/stores, which gcc wants
9 * even for soft-float, unless you use bruce evans' patches. The patches
10 * are great, but they have to be re-applied for every version, and the
11 * library is different for soft-float and 80387. So emulation is more
12 * practical, even though it's slower.
13 *
14 * 28.12.91 - loads/stores work, even BCD. I'll have to start thinking
15 * about add/sub/mul/div. Urgel. I should find some good source, but I'll
16 * just fake up something.
17 *
18 * 30.12.91 - add/sub/mul/div/com seem to work mostly. I should really
19 * test every possible combination.
20 */
/*
* ���淶Χ���ij��� 91.12.27 - ���������һЩ����/�洢ָ�������ʹ��
* ��Bruce Evans�IJ���������ʹʹ������ִ�и������㣬gccҲ��Ҫ��Щ
* ָ�Bruce�IJ�������dz��ã���ÿ�θ���gcc�汾�㶼���������������
* ���Ҷ�����������ʵ�ֺ�80387����ʹ�õĿ��Dz�ͬ�ġ����ʹ�÷����Ǹ�Ϊʵ
* �ʵķ��������ܷ��淽��������
*
* 91.12.28 - ����/�洢Э������ָ��������ˣ���ʹ��BCD���Ҳ��ʹ�á��ҽ�
* ��ʼ����ʵ�� add/sub/mul/div ָ�������Ӧ����һЩ�õ����ϣ���������
* �һ��ȷ���һЩ������
*
* 91.12.30 - add/sub/mul/div/com ��Щָ���������������ʹ���ˡ�����Ӧ
* �ò���ÿ��ָ����ܵ���ϲ�����
*/
21
22 /*
23 * This file is full of ugly macros etc: one problem was that gcc simply
24 * didn't want to make the structures as they should be: it has to try to
25 * align them. Sickening code, but at least I've hidden the ugly things
26 * in this one file: the other files don't need to know about these things.
27 *
28 * The other files also don't care about ST(x) etc - they just get addresses
29 * to 80-bit temporary reals, and do with them as they please. I wanted to
30 * hide most of the 387-specific things here.
31 */
/*
* ��������е�������Щ��Ť�ĺ꣺����֮һ��gcc���Dz���ѽṹ��������Ӧ��
* ��Ϊ�����ӣ�gcc ��ͼ�Խṹ���ж��봦�����������ᣬ�����������Ѿ�������
* ���ŵĴ��붼��������ôһ���ļ����ˣ����������ļ�����Ҫ�˽���Щ��Ϣ��
*
* �����ij���Ҳ����Ҫ֪��ST(x)��80387�ڲ��ṹ - ����ֻ��Ҫ�õ�80λ��ʱ
* ʵ���ĵ�ַ�Ϳ���������������뾡������������������387ר����Ϣ��
*/
32
33 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ţ��źŽṹ���źŲ�������ԭ�͡�
34
35 #define __ALIGNED_TEMP_REAL 1
36 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
37 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
38 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
39
40 #define bswapw(x) __asm__("xchgb %%al,%%ah":"=a" (x):"" ((short)x)) // ����2�ֽ�λ�á�
41 #define ST(x) (*__st((x))) // ȡ�����ST(x)�ۼ���ֵ��
42 #define PST(x) ((const temp_real *) __st((x))) // ȡ�����ST(x)�ۼ�����ָ�롣
43
44 /*
45 * We don't want these inlined - it gets too messy in the machine-code.
46 */
/*
* ���Dz�������Щ��ΪǶ������ - ��Ϊ���ʹ�õ��Ļ�����̫���ҡ�
*/
// ������Щ����ͬ���Ƹ���ָ��ķ��溯����
47 static void fpop(void);
48 static void fpush(void);
49 static void fxchg(temp_real_unaligned * a, temp_real_unaligned * b);
50 static temp_real_unaligned * __st(int i);
51
// ִ�и���ָ����档
// �ú������ȼ������I387�ṹ״̬�ּĴ������Ƿ���δ���ε��쳣��־��λ���������״
// ̬����æ��־B�������á�Ȼ���ָ��ָ�뱣����������ȡ������ָ�� EIP ���� 2�ֽڸ���
// ָ����� code�����ŷ������� code���������京����д�������Բ�ͬ��������ֵ��Linus
// ʹ���˼�����ͬ�� switch �������з��洦����
// ������info�ṹ��ָ�롣
52 static void do_emu(struct info * info)
53 {
54 unsigned short code;
55 temp_real tmp;
56 char * address;
57
// �ú������ȼ������I387�ṹ״̬�ּĴ������Ƿ���δ���ε��쳣��־��λ�����о�����
// ״̬���е�æ��־ B��λ15��������λ B��־��Ȼ�����ǰ�ָ��ָ�뱣���������ٿ���ִ
// �б������Ĵ����Ƿ����û����롣������ǣ��������ߵĴ����ѡ��������� 0x0f����˵��
// �ں����д���ʹ���˸���ָ���������ʾ������ָ����� CS��EIP ֵ����Ϣ���ں�����Ҫ
// ��ѧ��������ͣ����
58 if (I387.cwd & I387.swd & 0x3f)
59 I387.swd |= 0x8000; // ����æ��־B��
60 else
61 I387.swd &= 0x7fff; // ��æ��־B��
62 ORIG_EIP = EIP; // ���渡��ָ��ָ�롣
63 /* 0x0007 means user code space */
64 if (CS != 0x000F) { // �����û�������ͣ����
65 printk("math_emulate: %04x:%08x\n\r",CS,EIP);
66 panic("Math emulation needed in kernel");
67 }
// Ȼ������ȡ������ָ�� EIP ���� 2�ֽڸ���ָ����� code�� ����Intel CPU�洢����ʱ��
// ��Сͷ����Little endien����ǰ�ģ���ʱȡ���Ĵ���������ָ��ĵ�1����2�ֽ�˳��ߵ���
// ���������Ҫ����һ�� code �������ֽڵ�˳��Ȼ�������ε���1�������ֽ��е� ESC λ
// ��������11011�������ŰѸ���ָ��ָ��EIP���浽TSS��i387�ṹ�е�fip�ֶ��У���CS
// ���浽 fcs�ֶ��У�ͬʱ�����������ĸ���ָ����� code �ŵ� fcs �ֶεĸ� 16 λ�С�
// ������Щֵ��Ϊ���ڳ��ַ���Ĵ������쳣ʱ���������ʹ����ʵ��Э������һ�����д�����
// �����EIPָ�����ĸ���ָ����������
68 code = get_fs_word((unsigned short *) EIP); // ȡ2�ֽڵĸ���ָ����롣
69 bswapw(code); // �����ߵ��ֽڡ�
70 code &= 0x7ff; // ���δ����е�ESC�롣
71 I387.fip = EIP; // ����ָ��ָ�롣
72 *(unsigned short *) &I387.fcs = CS; // ��������ѡ�����
73 *(1+(unsigned short *) &I387.fcs) = code; // ������롣
74 EIP += 2; // ָ��ָ��ָ����һ���ֽڡ�
// Ȼ���������ֵcode���������京����д�������Բ�ͬ��������ֵ��Linusʹ���˼�����ͬ
// �� switch �������д��������ȣ���ָ��������Ǿ��й̶�����ֵ����Ĵ������أ�����
// �����洦����
75 switch (code) {
76 case 0x1d0: /* fnop */ /* �ղ���ָ��FNOP */
77 return;
78 case 0x1d1: case 0x1d2: case 0x1d3: // ��Чָ����롣���źţ��˳���
79 case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
80 math_abort(info,1<<(SIGILL-1));
81 case 0x1e0: // FCHS - �ı�ST����λ����ST = -ST��
82 ST(0).exponent ^= 0x8000;
83 return;
84 case 0x1e1: // FABS - ȡ����ֵ����ST = |ST|��
85 ST(0).exponent &= 0x7fff;
86 return;
87 case 0x1e2: case 0x1e3: // ��Чָ����롣���źţ��˳���
88 math_abort(info,1<<(SIGILL-1));
89 case 0x1e4: // FTST - ����TS��ͬʱ����״̬����Cn��
90 ftst(PST(0));
91 return;
92 case 0x1e5: // FXAM - ���TSֵ��ͬʱ��״̬����Cn��
93 printk("fxam not implemented\n\r"); // δʵ�֡����ź��˳���
94 math_abort(info,1<<(SIGILL-1));
95 case 0x1e6: case 0x1e7: // ��Чָ����롣���źţ��˳���
96 math_abort(info,1<<(SIGILL-1));
97 case 0x1e8: // FLD1 - ���س���1.0 ���ۼ���ST��
98 fpush();
99 ST(0) = CONST1;
100 return;
101 case 0x1e9: // FLDL2T - ���س���Log2(10) ���ۼ���ST��
102 fpush();
103 ST(0) = CONSTL2T;
104 return;
105 case 0x1ea: // FLDL2E - ���س���Log2(e) ���ۼ���ST��
106 fpush();
107 ST(0) = CONSTL2E;
108 return;
109 case 0x1eb: // FLDPI - ���س���Pi ���ۼ���ST��
110 fpush();
111 ST(0) = CONSTPI;
112 return;
113 case 0x1ec: // FLDLG2 - ���س���Log10(2) ���ۼ���ST��
114 fpush();
115 ST(0) = CONSTLG2;
116 return;
117 case 0x1ed: // FLDLN2 - ���س���Loge(2) ���ۼ���ST��
118 fpush();
119 ST(0) = CONSTLN2;
120 return;
121 case 0x1ee: // FLDZ - ���س���0.0 ���ۼ���ST��
122 fpush();
123 ST(0) = CONSTZ;
124 return;
125 case 0x1ef: // ��Ч��δʵ�ַ���ָ����롣���źţ��˳���
126 math_abort(info,1<<(SIGILL-1));
127 case 0x1f0: case 0x1f1: case 0x1f2: case 0x1f3:
128 case 0x1f4: case 0x1f5: case 0x1f6: case 0x1f7:
129 case 0x1f8: case 0x1f9: case 0x1fa: case 0x1fb:
130 case 0x1fc: case 0x1fd: case 0x1fe: case 0x1ff:
131 printk("%04x fxxx not implemented\n\r",code + 0xc800);
132 math_abort(info,1<<(SIGILL-1));
133 case 0x2e9: // FUCOMPP - ����Ƚϡ�
134 fucom(PST(1),PST(0));
135 fpop(); fpop();
136 return;
137 case 0x3d0: case 0x3d1: // FNOP - ��387��!!Ӧ����0x3e0, 0x3e1��
138 return;
139 case 0x3e2: // FCLEX - ��״̬�����쳣��־��
140 I387.swd &= 0x7f00;
141 return;
142 case 0x3e3: // FINIT - ��ʼ��Э��������
143 I387.cwd = 0x037f;
144 I387.swd = 0x0000;
145 I387.twd = 0x0000;
146 return;
147 case 0x3e4: // FNOP - ��80387��
148 return;
149 case 0x6d9: // FCOMPP - ST(1)��ST�Ƚϣ���ջ�������Ρ�
150 fcom(PST(1),PST(0));
151 fpop(); fpop();
152 return;
153 case 0x7e0: // FSTSW AX - ���浱ǰ״̬�ֵ�AX�Ĵ����С�
154 *(short *) &EAX = I387.swd;
155 return;
156 }
// ���濪ʼ������2�ֽ����3������REG��ָ���11011,XXXXXXXX,REG��ʽ�Ĵ��롣
157 switch (code >> 3) {
158 case 0x18: // FADD ST, ST(i)��
159 fadd(PST(0),PST(code & 7),&tmp);
160 real_to_real(&tmp,&ST(0));
161 return;
162 case 0x19: // FMUL ST, ST(i)��
163 fmul(PST(0),PST(code & 7),&tmp);
164 real_to_real(&tmp,&ST(0));
165 return;
166 case 0x1a: // FCOM ST(i)��
167 fcom(PST(code & 7),&tmp);
168 real_to_real(&tmp,&ST(0));
169 return;
170 case 0x1b: // FCOMP ST(i)��
171 fcom(PST(code & 7),&tmp);
172 real_to_real(&tmp,&ST(0));
173 fpop();
174 return;
175 case 0x1c: // FSUB ST, ST(i)��
176 real_to_real(&ST(code & 7),&tmp);
177 tmp.exponent ^= 0x8000;
178 fadd(PST(0),&tmp,&tmp);
179 real_to_real(&tmp,&ST(0));
180 return;
181 case 0x1d: // FSUBR ST, ST(i)��
182 ST(0).exponent ^= 0x8000;
183 fadd(PST(0),PST(code & 7),&tmp);
184 real_to_real(&tmp,&ST(0));
185 return;
186 case 0x1e: // FDIV ST, ST(i)��
187 fdiv(PST(0),PST(code & 7),&tmp);
188 real_to_real(&tmp,&ST(0));
189 return;
190 case 0x1f: // FDIVR ST, ST(i)��
191 fdiv(PST(code & 7),PST(0),&tmp);
192 real_to_real(&tmp,&ST(0));
193 return;
194 case 0x38: // FLD ST(i)��
195 fpush();
196 ST(0) = ST((code & 7)+1);
197 return;
198 case 0x39: // FXCH ST(i)��
199 fxchg(&ST(0),&ST(code & 7));
200 return;
201 case 0x3b: // FSTP ST(i)��
202 ST(code & 7) = ST(0);
203 fpop();
204 return;
205 case 0x98: // FADD ST(i), ST��
206 fadd(PST(0),PST(code & 7),&tmp);
207 real_to_real(&tmp,&ST(code & 7));
208 return;
209 case 0x99: // FMUL ST(i), ST��
210 fmul(PST(0),PST(code & 7),&tmp);
211 real_to_real(&tmp,&ST(code & 7));
212 return;
213 case 0x9a: // FCOM ST(i)��
214 fcom(PST(code & 7),PST(0));
215 return;
216 case 0x9b: // FCOMP ST(i)��
217 fcom(PST(code & 7),PST(0));
218 fpop();
219 return;
220 case 0x9c: // FSUBR ST(i), ST��
221 ST(code & 7).exponent ^= 0x8000;
222 fadd(PST(0),PST(code & 7),&tmp);
223 real_to_real(&tmp,&ST(code & 7));
224 return;
225 case 0x9d: // FSUB ST(i), ST��
226 real_to_real(&ST(0),&tmp);
227 tmp.exponent ^= 0x8000;
228 fadd(PST(code & 7),&tmp,&tmp);
229 real_to_real(&tmp,&ST(code & 7));
230 return;
231 case 0x9e: // FDIVR ST(i), ST��
232 fdiv(PST(0),PST(code & 7),&tmp);
233 real_to_real(&tmp,&ST(code & 7));
234 return;
235 case 0x9f: // FDIV ST(i), ST��
236 fdiv(PST(code & 7),PST(0),&tmp);
237 real_to_real(&tmp,&ST(code & 7));
238 return;
239 case 0xb8: // FFREE ST(i)��δʵ�֡�
240 printk("ffree not implemented\n\r");
241 math_abort(info,1<<(SIGILL-1));
242 case 0xb9: // FXCH ST(i)��
243 fxchg(&ST(0),&ST(code & 7));
244 return;
245 case 0xba: // FST ST(i)��
246 ST(code & 7) = ST(0);
247 return;
248 case 0xbb: // FSTP ST(i)��
249 ST(code & 7) = ST(0);
250 fpop();
251 return;
252 case 0xbc: // FUCOM ST(i)��
253 fucom(PST(code & 7),PST(0));
254 return;
255 case 0xbd: // FUCOMP ST(i)��
256 fucom(PST(code & 7),PST(0));
257 fpop();
258 return;
259 case 0xd8: // FADDP ST(i), ST��
260 fadd(PST(code & 7),PST(0),&tmp);
261 real_to_real(&tmp,&ST(code & 7));
262 fpop();
263 return;
264 case 0xd9: // FMULP ST(i), ST��
265 fmul(PST(code & 7),PST(0),&tmp);
266 real_to_real(&tmp,&ST(code & 7));
267 fpop();
268 return;
269 case 0xda: // FCOMP ST(i)��
270 fcom(PST(code & 7),PST(0));
271 fpop();
272 return;
273 case 0xdc: // FSUBRP ST(i), ST��
274 ST(code & 7).exponent ^= 0x8000;
275 fadd(PST(0),PST(code & 7),&tmp);
276 real_to_real(&tmp,&ST(code & 7));
277 fpop();
278 return;
279 case 0xdd: // FSUBP ST(i), ST��
280 real_to_real(&ST(0),&tmp);
281 tmp.exponent ^= 0x8000;
282 fadd(PST(code & 7),&tmp,&tmp);
283 real_to_real(&tmp,&ST(code & 7));
284 fpop();
285 return;
286 case 0xde: // FDIVRP ST(i), ST��
287 fdiv(PST(0),PST(code & 7),&tmp);
288 real_to_real(&tmp,&ST(code & 7));
289 fpop();
290 return;
291 case 0xdf: // FDIVP ST(i), ST��
292 fdiv(PST(code & 7),PST(0),&tmp);
293 real_to_real(&tmp,&ST(code & 7));
294 fpop();
295 return;
296 case 0xf8: // FFREE ST(i)��δʵ�֡�
297 printk("ffree not implemented\n\r");
298 math_abort(info,1<<(SIGILL-1));
299 fpop();
300 return;
301 case 0xf9: // FXCH ST(i)��
302 fxchg(&ST(0),&ST(code & 7));
303 return;
304 case 0xfa: // FSTP ST(i)��
305 case 0xfb: // FSTP ST(i)��
306 ST(code & 7) = ST(0);
307 fpop();
308 return;
309 }
// ������2���ֽ�λ7--6��MOD��λ2--0��R/M��ָ��� 11011,XXX,MOD,XXX,R/M ��ʽ��
// ���롣MOD�ڸ��ӳ����д�����������������ô�������0xe7��0b11100111�����ε�MOD��
310 switch ((code>>3) & 0xe7) {
311 case 0x22: // FST - ���浥����ʵ������ʵ������
312 put_short_real(PST(0),info,code);
313 return;
314 case 0x23: // FSTP - ���浥����ʵ������ʵ������
315 put_short_real(PST(0),info,code);
316 fpop();
317 return;
318 case 0x24: // FLDENV - ����Э������״̬�Ϳ��ƼĴ����ȡ�
319 address = ea(info,code);
320 for (code = 0 ; code < 7 ; code++) {
321 ((long *) & I387)[code] =
322 get_fs_long((unsigned long *) address);
323 address += 4;
324 }
325 return;
326 case 0x25: // FLDCW - ���ؿ����֡�
327 address = ea(info,code);
328 *(unsigned short *) &I387.cwd =
329 get_fs_word((unsigned short *) address);
330 return;
331 case 0x26: // FSTENV - ����Э������״̬�Ϳ��ƼĴ����ȡ�
332 address = ea(info,code);
333 verify_area(address,28);
334 for (code = 0 ; code < 7 ; code++) {
335 put_fs_long( ((long *) & I387)[code],
336 (unsigned long *) address);
337 address += 4;
338 }
339 return;
340 case 0x27: // FSTCW - ��������֡�
341 address = ea(info,code);
342 verify_area(address,2);
343 put_fs_word(I387.cwd,(short *) address);
344 return;
345 case 0x62: // FIST - �������������
346 put_long_int(PST(0),info,code);
347 return;
348 case 0x63: // FISTP - �������������
349 put_long_int(PST(0),info,code);
350 fpop();
351 return;
352 case 0x65: // FLD - ������չ����ʱ��ʵ����
353 fpush();
354 get_temp_real(&tmp,info,code);
355 real_to_real(&tmp,&ST(0));
356 return;
357 case 0x67: // FSTP - ������չʵ����
358 put_temp_real(PST(0),info,code);
359 fpop();
360 return;
361 case 0xa2: // FST - ����˫����ʵ����
362 put_long_real(PST(0),info,code);
363 return;
364 case 0xa3: // FSTP - ����˫����ʵ����
365 put_long_real(PST(0),info,code);
366 fpop();
367 return;
368 case 0xa4: // FRSTOR - �ָ�����108�ֽڵļĴ������ݡ�
369 address = ea(info,code);
370 for (code = 0 ; code < 27 ; code++) {
371 ((long *) & I387)[code] =
372 get_fs_long((unsigned long *) address);
373 address += 4;
374 }
375 return;
376 case 0xa6: // FSAVE - ��������108�ֽڼĴ������ݡ�
377 address = ea(info,code);
378 verify_area(address,108);
379 for (code = 0 ; code < 27 ; code++) {
380 put_fs_long( ((long *) & I387)[code],
381 (unsigned long *) address);
382 address += 4;
383 }
384 I387.cwd = 0x037f;
385 I387.swd = 0x0000;
386 I387.twd = 0x0000;
387 return;
388 case 0xa7: // FSTSW - ����״̬�֡�
389 address = ea(info,code);
390 verify_area(address,2);
391 put_fs_word(I387.swd,(short *) address);
392 return;
393 case 0xe2: // FIST - �������������
394 put_short_int(PST(0),info,code);
395 return;
396 case 0xe3: // FISTP - �������������
397 put_short_int(PST(0),info,code);
398 fpop();
399 return;
400 case 0xe4: // FBLD - ����BCD��������
401 fpush();
402 get_BCD(&tmp,info,code);
403 real_to_real(&tmp,&ST(0));
404 return;
405 case 0xe5: // FILD - ���س���������
406 fpush();
407 get_longlong_int(&tmp,info,code);
408 real_to_real(&tmp,&ST(0));
409 return;
410 case 0xe6: // FBSTP - ����BCD��������
411 put_BCD(PST(0),info,code);
412 fpop();
413 return;
414 case 0xe7: // BISTP - ���泤��������
415 put_longlong_int(PST(0),info,code);
416 fpop();
417 return;
418 }
// ���洦����2�ม��ָ����ȸ���ָ������λ10--9��MFֵȡָ�����͵�����Ȼ�����
// OPA��OPB�����ֵ���зֱ����������� 11011,MF,000,XXX,R/M��ʽ��ָ����롣
419 switch (code >> 9) {
420 case 0: // MF = 00����ʵ����32λʵ������
421 get_short_real(&tmp,info,code);
422 break;
423 case 1: // MF = 01����������32�������
424 get_long_int(&tmp,info,code);
425 break;
426 case 2: // MF = 10����ʵ����64λʵ������
427 get_long_real(&tmp,info,code);
428 break;
429 case 4: // MF = 11����������64λ����������Ӧ��case 3��
430 get_short_int(&tmp,info,code);
431 }
// ��������ָ���2�ֽ��е�OPB���롣
432 switch ((code>>3) & 0x27) {
433 case 0: // FADD��
434 fadd(&tmp,PST(0),&tmp);
435 real_to_real(&tmp,&ST(0));
436 return;
437 case 1: // FMUL��
438 fmul(&tmp,PST(0),&tmp);
439 real_to_real(&tmp,&ST(0));
440 return;
441 case 2: // FCOM��
442 fcom(&tmp,PST(0));
443 return;
444 case 3: // FCOMP��
445 fcom(&tmp,PST(0));
446 fpop();
447 return;
448 case 4: // FSUB��
449 tmp.exponent ^= 0x8000;
450 fadd(&tmp,PST(0),&tmp);
451 real_to_real(&tmp,&ST(0));
452 return;
453 case 5: // FSUBR��
454 ST(0).exponent ^= 0x8000;
455 fadd(&tmp,PST(0),&tmp);
456 real_to_real(&tmp,&ST(0));
457 return;
458 case 6: // FDIV��
459 fdiv(PST(0),&tmp,&tmp);
460 real_to_real(&tmp,&ST(0));
461 return;
462 case 7: // FDIVR��
463 fdiv(&tmp,PST(0),&tmp);
464 real_to_real(&tmp,&ST(0));
465 return;
466 }
// �������� 11011,XX,1,XX,000,R/M ��ָ����롣
467 if ((code & 0x138) == 0x100) { // FLD��FILD��
468 fpush();
469 real_to_real(&tmp,&ST(0));
470 return;
471 }
// �����Ϊ��Чָ�
472 printk("Unknown math-insns: %04x:%08x %04x\n\r",CS,EIP,code);
473 math_abort(info,1<<(SIGFPE-1));
474 }
475
// CPU�쳣�ж�int7���õ�80387����ӿں�����
// ����ǰ����û��ʹ�ù�Э��������������ʹ��Э��������־used_math��Ȼ���ʼ��80387
// �Ŀ����֡�״̬�ֺ������֡����ʹ���ж�int7���ñ������ķ��ص�ַָ����Ϊ��������
// ����ָ�����������do_emu()��
// ���� ___false �� _orig_eip��
476 void math_emulate(long ___false)
477 {
478 if (!current->used_math) {
479 current->used_math = 1;
480 I387.cwd = 0x037f;
481 I387.swd = 0x0000;
482 I387.twd = 0x0000;
483 }
484 /* &___false points to info->___orig_eip, so subtract 1 to get info */
485 do_emu((struct info *) ((&___false) - 1));
486 }
487
// ��ֹ���������
// ����������Чָ��������δʵ�ֵ�ָ�����ʱ���ú������Ȼָ������ԭEIP��������ָ��
// �źŸ���ǰ���̡����ջָ��ָ���ж�int7 �������̵��ñ������ķ��ص�ַ��ֱ�ӷ��ص�
// �жϴ��������С�
488 void __math_abort(struct info * info, unsigned int signal)
489 {
490 EIP = ORIG_EIP;
491 current->signal |= signal;
492 __asm__("movl %0,%%esp ; ret"::"g" ((long) info));
493 }
494
// �ۼ���ջ����������
// ��״̬��TOP�ֶ�ֵ��1������7ȡģ��
495 static void fpop(void)
496 {
497 unsigned long tmp;
498
499 tmp = I387.swd & 0xffffc7ff;
500 I387.swd += 0x00000800;
501 I387.swd &= 0x00003800;
502 I387.swd |= tmp;
503 }
504
// �ۼ���ջ��ջ������
// ��״̬��TOP�ֶμ�1������7��������7ȡģ��
505 static void fpush(void)
506 {
507 unsigned long tmp;
508
509 tmp = I387.swd & 0xffffc7ff;
510 I387.swd += 0x00003800;
511 I387.swd &= 0x00003800;
512 I387.swd |= tmp;
513 }
514
// ���������ۼ����Ĵ�����ֵ��
515 static void fxchg(temp_real_unaligned * a, temp_real_unaligned * b)
516 {
517 temp_real_unaligned c;
518
519 c = *a;
520 *a = *b;
521 *b = c;
522 }
523
// ȡST(i)���ڴ�ָ�롣
// ȡ״̬����TOP�ֶ�ֵ������ָ�����������ݼĴ����Ų�ȡģ�����ST(i)��Ӧ��ָ�롣
524 static temp_real_unaligned * __st(int i)
525 {
526 i += I387.swd >> 11; // ȡ״̬����TOP�ֶ�ֵ��
527 i &= 7;
528 return (temp_real_unaligned *) (i*10 + (char *)(I387.st_space));
529 }
530
1 /*
2 * linux/kernel/math/error.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źŲ�������ԭ�͡�
8
9 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
10
// Э�����������ж�int16���õĴ���������
// ��Э���������Լ���������ʱ���ͻ�ͨ��ERROR����֪ͨCPU������������ڴ���Э����
// �������ij����źš�����תȥִ�� math_error()�����غ���ת�����ret_from_sys_call
// ������ִ�С�
11 void math_error(void)
12 {
13 __asm__("fnclex"); // ��80387���״̬���������쳣��־λ��æλ��
14 if (last_task_used_math) // ��ʹ����Э��������������Э�����������źš�
15 last_task_used_math->signal |= 1<<(SIGFPE-1);
16 }
17
1 /*
2 * linux/kernel/math/ea.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * Calculate the effective address.
9 */
/*
* ������Ч��ַ��
*/
10
11 #include <stddef.h> // ������ͷ�ļ���������ʹ�������е�offsetof()���塣
12
13 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
14 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
15
// info�ṹ�и����Ĵ����ڽṹ�е�ƫ��λ�á�offsetof()������ָ���ֶ��ڽṹ�е�ƫ��λ
// �á��μ�include/stddef.h�ļ���
16 static int __regoffset[] = {
17 offsetof(struct info,___eax),
18 offsetof(struct info,___ecx),
19 offsetof(struct info,___edx),
20 offsetof(struct info,___ebx),
21 offsetof(struct info,___esp),
22 offsetof(struct info,___ebp),
23 offsetof(struct info,___esi),
24 offsetof(struct info,___edi)
25 };
26
// ȡinfo�ṹ��ָ��λ�ô��Ĵ������ݡ�
27 #define REG(x) (*(long *)(__regoffset[(x)]+(char *) info))
28
// ��2�ֽ�Ѱַģʽ�е�2������ָʾ�ֽ�SIB��Scale��Index��Base����ֵ��
29 static char * sib(struct info * info, int mod)
30 {
31 unsigned char ss,index,base;
32 long offset = 0;
33
// ���ȴ��û��������ȡ��SIB�ֽڣ�Ȼ��ȡ�������ֶα���λֵ��
34 base = get_fs_byte((char *) EIP);
35 EIP++;
36 ss = base >> 6; // �������Ӵ�Сss��
37 index = (base >> 3) & 7; // ����ֵ��������index��
38 base &= 7; // ����ַ����base��
// �����������Ϊ0b100����ʾ������ƫ��ֵ����������ƫ��ֵoffset=��Ӧ�Ĵ�������*�������ӡ�
39 if (index == 4)
40 offset = 0;
41 else
42 offset = REG(index);
43 offset <<= ss;
// �����һMODRM�ֽ��е�MOD��Ϊ�㣬����Base������0b101�����ʾ��ƫ��ֵ��baseָ����
// �Ĵ����С����ƫ��offset��Ҫ�ټ���base��Ӧ�Ĵ����е����ݡ�
44 if (mod || base != 5)
45 offset += REG(base);
// ���MOD=1�����ʾƫ��ֵΪ1�ֽڡ�������MOD=2������base=0b101����ƫ��ֵΪ4�ֽڡ�
46 if (mod == 1) {
47 offset += (signed char) get_fs_byte((char *) EIP);
48 EIP++;
49 } else if (mod == 2 || base == 5) {
50 offset += (signed) get_fs_long((unsigned long *) EIP);
51 EIP += 4;
52 }
// ��沢����ƫ��ֵ��
53 I387.foo = offset;
54 I387.fos = 0x17;
55 return (char *) offset;
56 }
57
// ����ָ����Ѱַģʽ�ֽڼ�����Ч��ֵַ��
58 char * ea(struct info * info, unsigned short code)
59 {
60 unsigned char mod,rm;
61 long * tmp = &EAX;
62 int offset = 0;
63
// ����ȡ�����е�MOD�ֶκ�R/M�ֶ�ֵ�����MOD=0b11����ʾ�ǵ��ֽ�ָ�û��ƫ���ֶΡ�
// ���R/M�ֶ�=0b100������MOD��Ϊ0b11����ʾ��2�ֽڵ�ַģʽѰַ����˵���sib()��
// ��ƫ��ֵ�����ؼ��ɡ�
64 mod = (code >> 6) & 3; // MOD�ֶΡ�
65 rm = code & 7; // R/M�ֶΡ�
66 if (rm == 4 && mod != 3)
67 return sib(info,mod);
// ���R/M�ֶ�Ϊ0b101������MODΪ0����ʾ�ǵ��ֽڵ�ַģʽ�����Һ���32�ֽ�ƫ��ֵ��
// ����ȡ���û�������4�ֽ�ƫ��ֵ�����沢����֮��
68 if (rm == 5 && !mod) {
69 offset = get_fs_long((unsigned long *) EIP);
70 EIP += 4;
71 I387.foo = offset;
72 I387.fos = 0x17;
73 return (char *) offset;
74 }
// ������������������MOD���д���������ȡ��R/M�����Ӧ�Ĵ������ݵ�ֵ��Ϊָ��tmp��
// ����MOD=0����ƫ��ֵ������MOD=1���������1�ֽ�ƫ��ֵ������MOD=2���������4�ֽ�
// ƫ��ֵ����沢������Ч��ֵַ��
75 tmp = & REG(rm);
76 switch (mod) {
77 case 0: offset = 0; break;
78 case 1:
79 offset = (signed char) get_fs_byte((char *) EIP);
80 EIP++;
81 break;
82 case 2:
83 offset = (signed) get_fs_long((unsigned long *) EIP);
84 EIP += 4;
85 break;
86 case 3:
87 math_abort(info,1<<(SIGILL-1));
88 }
89 I387.foo = offset;
90 I387.fos = 0x17;
91 return offset + (char *) *tmp;
92 }
93
1 /*
2 * linux/kernel/math/convert.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
8
9 /*
10 * NOTE!!! There is some "non-obvious" optimisations in the temp_to_long
11 * and temp_to_short conversion routines: don't touch them if you don't
12 * know what's going on. They are the adding of one in the rounding: the
13 * overflow bit is also used for adding one into the exponent. Thus it
14 * looks like the overflow would be incorrectly handled, but due to the
15 * way the IEEE numbers work, things are correct.
16 *
17 * There is no checking for total overflow in the conversions, though (ie
18 * if the temp-real number simply won't fit in a short- or long-real.)
19 */
/*
* ע��!!! ��temp_to_long��temp_to_short��������ת���ӳ�������Щ�������ԡ�
* ���Ż����������������Ͳ�Ҫ�����ġ���������������еļ�1�����λҲͬ
* ����������ָ���м�1����˿���ȥ�������û�б���ȷ�ش�������������IEEE
* �����������涨���ݸ�ʽ�IJ�����ʽ����Щ��������ȷ�ġ�
*
* ��������û�ж�ת�������������������⣨Ҳ����ʱʵ���Ƿ��ܹ��ط����
* ʵ����ʵ����ʽ�У���
*/
20
// ��ʵ��ת������ʱʵ����ʽ��
// ��ʵ��������32λ������Ч����β����������23λ��ָ����8λ������1������λ��
21 void short_to_temp(const short_real * a, temp_real * b)
22 {
// ���ȴ�����ת���Ķ�ʵ����0���������Ϊ0�������ö�Ӧ��ʱʵ��b����Ч��Ϊ0��Ȼ���
// �ݶ�ʵ������λ������ʱʵ���ķ���λ����exponent�������Чλ��
23 if (!(*a & 0x7fffffff)) {
24 b->a = b->b = 0; // ����ʱʵ������Ч�� = 0��
25 if (*a)
26 b->exponent = 0x8000; // ���÷���λ��
27 else
28 b->exponent = 0;
29 return;
30 }
// ����һ���ʵ������ȷ����Ӧ��ʱʵ����ָ��ֵ��������Ҫ�õ�������ƫ�ñ�ʾ�����ĸ��
// ��ʵ��ָ����ƫ������127������ʱʵ��ָ����ƫ������16383�������ȡ����ʵ����ָ��ֵ
// ����Ҫ������е�ƫ����Ϊ 16383�� ��ʱ���γ�����ʱʵ����ʽ��ָ��ֵ exponent�����⣬
// �����ʵ���Ǹ���������Ҫ������ʱʵ���ķ���λ��λ79������һ������β��ֵ�������ǰ�
// ��ʵ������8λ����23λβ�������Чλ������ʱʵ����λ62��������ʱʵ��β����λ63
// ����Ҫ����һ��1������Ҫ����0x80000000����������ʱʵ����32λ��Ч����
31 b->exponent = ((*a>>23) & 0xff)-127+16383; // ȡ����ʵ��ָ��λ������ƫ������
32 if (*a<0)
33 b->exponent |= 0x8000; // ��Ϊ���������÷���λ��
34 b->b = (*a<<8) | 0x80000000; // ����β�������ӹ̶�1ֵ��
35 b->a = 0;
36 }
37
// ��ʵ��ת������ʱʵ����ʽ��
// ������short_to_temp()��ȫһ����������ʵ��ָ��ƫ������1023��
38 void long_to_temp(const long_real * a, temp_real * b)
39 {
40 if (!a->a && !(a->b & 0x7fffffff)) {
41 b->a = b->b = 0; // ����ʱʵ������Ч�� = 0��
42 if (a->b)
43 b->exponent = 0x8000; // ���÷���λ��
44 else
45 b->exponent = 0;
46 return;
47 }
48 b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383; // ȡ��ʵ��ָ��������ƫ������
49 if (a->b<0)
50 b->exponent |= 0x8000; // ��Ϊ���������÷���λ��
51 b->b = 0x80000000 | (a->b<<11) | (((unsigned long)a->a)>>21); // ���������1��
52 b->a = a->a<<11;
53 }
54
// ��ʱʵ��ת���ɶ�ʵ����ʽ��
// ������short_to_temp()�෴������Ҫ�������Ⱥ��������⡣
55 void temp_to_short(const temp_real * a, short_real * b)
56 {
// ���ָ������Ϊ0�������������λ���ö�ʵ��Ϊ-0 ��0��
57 if (!(a->exponent & 0x7fff)) {
58 *b = (a->exponent)?0x80000000:0;
59 return;
60 }
// �ȴ���ָ�����֡���������ʱʵ��ָ��ƫ������16383��Ϊ��ʵ����ƫ����127��
61 *b = ((((long) a->exponent)-16383+127) << 23) & 0x7f800000;
62 if (a->exponent < 0) // ���Ǹ��������÷���λ��
63 *b |= 0x80000000;
64 *b |= (a->b >> 8) & 0x007fffff; // ȡ��ʱʵ����Ч����23λ��
// ���ݿ������е���������ִ�����������
65 switch (ROUNDING) {
66 case ROUND_NEAREST:
67 if ((a->b & 0xff) > 0x80)
68 ++*b;
69 break;
70 case ROUND_DOWN:
71 if ((a->exponent & 0x8000) && (a->b & 0xff))
72 ++*b;
73 break;
74 case ROUND_UP:
75 if (!(a->exponent & 0x8000) && (a->b & 0xff))
76 ++*b;
77 break;
78 }
79 }
80
// ��ʱʵ��ת���ɳ�ʵ����
81 void temp_to_long(const temp_real * a, long_real * b)
82 {
83 if (!(a->exponent & 0x7fff)) {
84 b->a = 0;
85 b->b = (a->exponent)?0x80000000:0;
86 return;
87 }
88 b->b = (((0x7fff & (long) a->exponent)-16383+1023) << 20) & 0x7ff00000;
89 if (a->exponent < 0)
90 b->b |= 0x80000000;
91 b->b |= (a->b >> 11) & 0x000fffff;
92 b->a = a->b << 21;
93 b->a |= (a->a >> 11) & 0x001fffff;
94 switch (ROUNDING) {
95 case ROUND_NEAREST:
96 if ((a->a & 0x7ff) > 0x400)
97 __asm__("addl $1,%0 ; adcl $0,%1"
98 :"=r" (b->a),"=r" (b->b)
99 :"" (b->a),"1" (b->b));
100 break;
101 case ROUND_DOWN:
102 if ((a->exponent & 0x8000) && (a->b & 0xff))
103 __asm__("addl $1,%0 ; adcl $0,%1"
104 :"=r" (b->a),"=r" (b->b)
105 :"" (b->a),"1" (b->b));
106 break;
107 case ROUND_UP:
108 if (!(a->exponent & 0x8000) && (a->b & 0xff))
109 __asm__("addl $1,%0 ; adcl $0,%1"
110 :"=r" (b->a),"=r" (b->b)
111 :"" (b->a),"1" (b->b));
112 break;
113 }
114 }
115
// ��ʱʵ��ת������ʱ������ʽ��
// ��ʱ����Ҳ��10�ֽڱ�ʾ�����е�8�ֽ�����������ֵ����2�ֽڱ�ʾָ��ֵ�ͷ���λ��
// �����2�ֽ������ЧλΪ1�����ʾ�Ǹ�������λ0����ʾ��������
116 void real_to_int(const temp_real * a, temp_int * b)
117 {
118 int shift = 16383 + 63 - (a->exponent & 0x7fff);
119 unsigned long underflow;
120
121 b->a = b->b = underflow = 0;
122 b->sign = (a->exponent < 0);
123 if (shift < 0) {
124 set_OE();
125 return;
126 }
127 if (shift < 32) {
128 b->b = a->b; b->a = a->a;
129 } else if (shift < 64) {
130 b->a = a->b; underflow = a->a;
131 shift -= 32;
132 } else if (shift < 96) {
133 underflow = a->b;
134 shift -= 64;
135 } else
136 return;
137 __asm__("shrdl %2,%1,%0"
138 :"=r" (underflow),"=r" (b->a)
139 :"c" ((char) shift),"" (underflow),"1" (b->a));
140 __asm__("shrdl %2,%1,%0"
141 :"=r" (b->a),"=r" (b->b)
142 :"c" ((char) shift),"" (b->a),"1" (b->b));
143 __asm__("shrl %1,%0"
144 :"=r" (b->b)
145 :"c" ((char) shift),"" (b->b));
146 switch (ROUNDING) {
147 case ROUND_NEAREST:
148 __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
149 :"=r" (b->a),"=r" (b->b)
150 :"" (b->a),"1" (b->b)
151 ,"r" (0x7fffffff + (b->a & 1))
152 ,"m" (*&underflow));
153 break;
154 case ROUND_UP:
155 if (!b->sign && underflow)
156 __asm__("addl $1,%0 ; adcl $0,%1"
157 :"=r" (b->a),"=r" (b->b)
158 :"" (b->a),"1" (b->b));
159 break;
160 case ROUND_DOWN:
161 if (b->sign && underflow)
162 __asm__("addl $1,%0 ; adcl $0,%1"
163 :"=r" (b->a),"=r" (b->b)
164 :"" (b->a),"1" (b->b));
165 break;
166 }
167 }
168
// ��ʱ����ת������ʱʵ����ʽ��
169 void int_to_real(const temp_int * a, temp_real * b)
170 {
// ����ԭֵ������������ת������ʱʵ��ʱָ��������Ҫ����ƫ����16383�⣬��Ҫ����63��
// ��ʾ��Ч��Ҫ����2��63�η�������������ֵ��
171 b->a = a->a;
172 b->b = a->b;
173 if (b->a || b->b)
174 b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
175 else {
176 b->exponent = 0;
177 return;
178 }
// �Ը�ʽת�������ʱʵ�����й������������Ч�������Чλ����0��
179 while (b->b >= 0) {
180 b->exponent--;
181 __asm__("addl %0,%0 ; adcl %1,%1"
182 :"=r" (b->a),"=r" (b->b)
183 :"" (b->a),"1" (b->b));
184 }
185 }
186
1 /*
2 * linux/kernel/math/add.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * temporary real addition routine.
9 *
10 * NOTE! These aren't exact: they are only 62 bits wide, and don't do
11 * correct rounding. Fast hack. The reason is that we shift right the
12 * values by two, in order not to have overflow (1 bit), and to be able
13 * to move the sign into the mantissa (1 bit). Much simpler algorithms,
14 * and 62 bits (61 really - no rounding) accuracy is usually enough. The
15 * only time you should notice anything weird is when adding 64-bit
16 * integers together. When using doubles (52 bits accuracy), the
17 * 61-bit accuracy never shows at all.
18 */
/*
* ��ʱʵ���ӷ��ӳ���
*
* ע�⣡ ��Щ������ȷ������ֻ��62���ؿ��ȣ����Ҳ��ܽ�����ȷ�����������
* ��Щ���Dzݾ�֮����ԭ����Ϊ�˲��������1���أ������ǰ�ֵ������2λ��
* ����ʹ�÷���λ��1���أ��ܹ�����β���С����Ƿdz����㷨������62λ
* ��ʵ������61λ - û�����룩�ľ���ͨ��Ҳ�㹻�ˡ�ֻ�е����64λ������
* ���ʱ�Żᷢ��һЩ��ֵ����⡣��ʹ��˫���ȣ�52���ؾ��ȣ�����ʱ������
* Զ�����ܳ���61���ؾ��ȵġ�
*/
19
20 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
21
// ��һ�����ĸ����������Ʋ��룩��ʾ��
// ����ʱʵ��β������Ч����ȡ�����ټ�1��
// ����a����ʱʵ���ṹ������a��b�ֶ������ʵ������Ч����
22 #define NEGINT(a) \
23 __asm__("notl %0 ; notl %1 ; addl $1,%0 ; adcl $0,%1" \
24 :"=r" (a->a),"=r" (a->b) \
25 :"" (a->a),"1" (a->b))
26
// β�����Ż���
// ������ʱʵ���任��ָ����������ʾ��ʽ���Ա��ڷ������㡣��������������Ϊ�����ʽ��
27 static void signify(temp_real * a)
28 {
// ��64λ������β������2λ�����ָ����Ҫ��2������Ϊָ���ֶ�exponent����߱���λ��
// ����λ��������ָ��ֵС���㣬˵�������Ǹ������������β���ò����ʾ��ȡ������Ȼ���
// ָ��ȡ��ֵ����ʱβ���в��������ƹ�2λ����Ч�������һ�������ֵ�ķ���λ��
// 30���ϣ�%0 - a->a��%1 - a->b�����ָ�shrdl $2, %1, %0��ִ��˫���ȣ�64λ�����ƣ�
// �������β��<b,a>����2λ�����ڸ��ƶ���������ı�%1��a->b���е�ֵ����˻���Ҫ����
// ��������2�
29 a->exponent += 2;
30 __asm__("shrdl $2,%1,%0 ; shrl $2,%1" // ʹ��˫����ָ���β������2λ��
31 :"=r" (a->a),"=r" (a->b)
32 :"" (a->a),"1" (a->b));
33 if (a->exponent < 0) // �Ǹ�������β���ò����ʾ��ȡ��ֵ����
34 NEGINT(a);
35 a->exponent &= 0x7fff; // ȥ������λ�����У���
36 }
37
// β���Ƿ��Ż���
// �������ʽת��Ϊ��ʱʵ����ʽ������ָ����������ʾ��ʵ��ת��Ϊ��ʱʵ����ʽ��
38 static void unsignify(temp_real * a)
39 {
// ����ֵΪ0�������ô�����ֱ�ӷ��ء����������ȸ�λ��ʱʵ����ʽ�ķ���λ��Ȼ���ж�
// β���ĸ�λlong�ֶ�a->b�Ƿ���з���λ�����У����� exponent �ֶ����ӷ���λ��ͬʱ
// ��β������������ʽ��ʾ��ȡ����������β�����й������ͬʱָ��ֵ����Ӧ�ݼ���
// ��ִ�����Ʋ�����ʹ��β�������Чλ��Ϊ0�����a->bֵ����Ϊ��ֵ����
40 if (!(a->a || a->b)) { // ��ֵΪ0�ͷ��ء�
41 a->exponent = 0;
42 return;
43 }
44 a->exponent &= 0x7fff; // ȥ������λ�����У���
45 if (a->b < 0) { // �Ǹ�������β��ȡ��ֵ��
46 NEGINT(a);
47 a->exponent |= 0x8000; // ��ʱʵ�������÷���λ��
48 }
49 while (a->b >= 0) {
50 a->exponent--; // ��β�����й������
51 __asm__("addl %0,%0 ; adcl %1,%1"
52 :"=r" (a->a),"=r" (a->b)
53 :"" (a->a),"1" (a->b));
54 }
55 }
56
// ���渡��ӷ�ָ�����㡣
// ��ʱʵ������ src1 + src2 �� result��
57 void fadd(const temp_real * src1, const temp_real * src2, temp_real * result)
58 {
59 temp_real a,b;
60 int x1,x2,shift;
61
// ����ȡ��������ָ��ֵx1��x2��ȥ������λ����Ȼ���ñ���a�����������ֵ��shiftΪָ��
// ��ֵ�������2�ı���ֵ����
62 x1 = src1->exponent & 0x7fff;
63 x2 = src2->exponent & 0x7fff;
64 if (x1 > x2) {
65 a = *src1;
66 b = *src2;
67 shift = x1-x2;
68 } else {
69 a = *src2;
70 b = *src1;
71 shift = x2-x1;
72 }
// ���������̫���ڵ���2��64�η��������ǿ��Ժ���С���Ǹ�������bֵ������ֱ�ӷ�
// ��aֵ���ɡ������������ڵ���2��32�η�����ô���ǿ��Ժ���Сֵb�еĵ�32λֵ��
// �������ǰ� b�ĸ�long�ֶ�ֵ b.b����32λ�����ŵ�b.a�С�Ȼ���b��ָ��ֵ��Ӧ����
// ��32�η�����ָ����ֵ��ȥ32����������֮����ӵ���������β��������������ͬ�����С�
73 if (shift >= 64) {
74 *result = a;
75 return;
76 }
77 if (shift >= 32) {
78 b.a = b.b;
79 b.b = 0;
80 shift -= 32;
81 }
// �����ٽ���ϸ�µص������Խ�������ߵ�������ͬ�����������ǰ�Сֵb��β������shift
// ������λ���������ߵ�ָ����ͬ������ͬһ���������¡����ǾͿ��Զ�β��������������ˡ�
// ���֮ǰ������Ҫ�Ȱ�����ת���ɷ��������ʽ���ڼӷ�������ٱ任����ʱʵ����ʽ��
82 __asm__("shrdl %4,%1,%0 ; shrl %4,%1" // ˫���ȣ�64λ�����ơ�
83 :"=r" (b.a),"=r" (b.b)
84 :"" (b.a),"1" (b.b),"c" ((char) shift));
85 signify(&a); // �任��ʽ��
86 signify(&b);
87 __asm__("addl %4,%0 ; adcl %5,%1" // ִ�мӷ����㡣
88 :"=r" (a.a),"=r" (a.b)
89 :"" (a.a),"1" (a.b),"g" (b.a),"g" (b.b));
90 unsignify(&a); // �ٱ任����ʱʵ����ʽ��
91 *result = a;
92 }
93
1 /*
2 * linux/kernel/math/compare.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * temporary real comparison routines
9 */
/*
* �ۼ�������ʱʵ���Ƚ��ӳ���
*/
10
11 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
12
// ��λ״̬���е�C3��C2��C1��C0����λ��
13 #define clear_Cx() (I387.swd &= ~0x4500)
14
// ����ʱʵ��a���й����������ʾ��ָ������Ч����ʽ��
// ���磺102.345 ��ʾ�� 1.02345 X 102�� 0.0001234 ��ʾ�� 1.234 X 10-4����Ȼ����������
// �����Ʊ�ʾ��
15 static void normalize(temp_real * a)
16 {
17 int i = a->exponent & 0x7fff; // ȡָ��ֵ����ȥ����λ����
18 int sign = a->exponent & 0x8000; // ȡ����λ��
19
// �����ʱʵ��a��64λ��Ч����β����Ϊ0����ô˵��a����0��������a��ָ���������ء�
20 if (!(a->a || a->b)) {
21 a->exponent = 0;
22 return;
23 }
// ���a��β���������0ֵ����λ����ô��β�����ƣ�ͬʱ����ָ��ֵ���ݼ�����ֱ��β��
// ��b�ֶ������ЧλMSB��1λ�ã���ʱb����Ϊ��ֵ��������������Ϸ���λ��
24 while (i && a->b >= 0) {
25 i--;
26 __asm__("addl %0,%0 ; adcl %1,%1"
27 :"=r" (a->a),"=r" (a->b)
28 :"" (a->a),"1" (a->b));
29 }
30 a->exponent = i | sign;
31 }
32
// ���渡��ָ��FTST��
// ��ջ���ۼ���ST(0)��0�Ƚϣ������ݱȽϽ����������λ����ST > 0.0����C3��C2��C0
// �ֱ�Ϊ000����ST < 0.0��������λΪ001����ST == 0.0��������λ��100�������ɱȽϣ�
// ������λΪ111��
33 void ftst(const temp_real * a)
34 {
35 temp_real b;
36
// ������״̬����������־λ�����ԱȽ�ֵb��ST�����й��������b�������㲢������
// �˷���λ���Ǹ�����������������λC0��������������λC3��
37 clear_Cx();
38 b = *a;
39 normalize(&b);
40 if (b.a || b.b || b.exponent) {
41 if (b.exponent < 0)
42 set_C0();
43 } else
44 set_C3();
45 }
46
// ���渡��ָ��FCOM��
// �Ƚ���������src1��src2�������ݱȽϽ����������λ����src1 > src2����C3��C2��C0
// �ֱ�Ϊ000����src1 < src2��������λΪ001����������ȣ�������λ��100��
47 void fcom(const temp_real * src1, const temp_real * src2)
48 {
49 temp_real a;
50
51 a = *src1;
52 a.exponent ^= 0x8000; // ����λȡ����
53 fadd(&a,src2,&a); // ������ӣ����������
54 ftst(&a); // ���Խ������������λ��
55 }
56
// ���渡��ָ��FUCOM������Ƚϣ���
// ���ڲ�����֮һ��NaN�ıȽϡ�
57 void fucom(const temp_real * src1, const temp_real * src2)
58 {
59 fcom(src1,src2);
60 }
61
1 /*
2 * linux/kernel/math/get_put.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This file handles all accesses to user memory: getting and putting
9 * ints/reals/BCD etc. This is the only part that concerns itself with
10 * other than temporary real format. All other cals are strictly temp_real.
11 */
/*
* �����������ж��û��ڴ�ķ��ʣ���ȡ�ʹ���ָ��/ʵ��ֵ/BCD��ֵ�ȡ�����
* �漰��ʱʵ������������ʽ���еIJ��֡�������������ȫ��ʹ����ʱʵ����ʽ��
*/
12 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ţ��źŽṹ���źŲ�������ԭ�͡�
13
14 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
15 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
16 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
17
// ȡ�û��ڴ��еĶ�ʵ����������ʵ������
// ���ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ö�ʵ��
// ������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧʵ��ֵ�������û���ʵ��ת����
// ��ʱʵ����math/convert.c����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
18 void get_short_real(temp_real * tmp,
19 struct info * info, unsigned short code)
20 {
21 char * addr;
22 short_real sr;
23
24 addr = ea(info,code); // ������Ч��ַ��
25 sr = get_fs_long((unsigned long *) addr); // ȡ�û��������е�ֵ��
26 short_to_temp(&sr,tmp); // ת������ʱʵ����ʽ��
27 }
28
// ȡ�û��ڴ��еij�ʵ����˫����ʵ������
// ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ó�
// ʵ��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧʵ��ֵ�������û�ʵ��ֵת
// ������ʱʵ����math/convert.c����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
29 void get_long_real(temp_real * tmp,
30 struct info * info, unsigned short code)
31 {
32 char * addr;
33 long_real lr;
34
35 addr = ea(info,code); // ȡָ���е���Ч��ֵַ��
36 lr.a = get_fs_long((unsigned long *) addr); // ȡ��8�ֽ�ʵ����
37 lr.b = get_fs_long(1 + (unsigned long *) addr);
38 long_to_temp(&lr,tmp); // ת������ʱʵ����ʽ��
39 }
40
// ȡ�û��ڴ��е���ʱʵ����
// ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ����
// ʱʵ��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ��ʱʵ��ֵ��
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
41 void get_temp_real(temp_real * tmp,
42 struct info * info, unsigned short code)
43 {
44 char * addr;
45
46 addr = ea(info,code); // ȡָ���е���Ч��ֵַ��
47 tmp->a = get_fs_long((unsigned long *) addr);
48 tmp->b = get_fs_long(1 + (unsigned long *) addr);
49 tmp->exponent = get_fs_word(4 + (unsigned short *) addr);
50 }
51
// ȡ�û��ڴ��еĶ�������ת������ʱʵ����ʽ��
// ��ʱ����Ҳ��10�ֽڱ�ʾ�����е�8�ֽ�����������ֵ����2�ֽڱ�ʾָ��ֵ�ͷ���λ��
// �����2�ֽ������ЧλΪ1�����ʾ�Ǹ������������Чλ��0����ʾ��������
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ� info�ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ö�����������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��ʱ
// ������ʽ��������ʱ����ֵת������ʱʵ����math/convert.c����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
52 void get_short_int(temp_real * tmp,
53 struct info * info, unsigned short code)
54 {
55 char * addr;
56 temp_int ti;
57
58 addr = ea(info,code); // ȡָ���е���Ч��ֵַ��
59 ti.a = (signed short) get_fs_word((unsigned short *) addr);
60 ti.b = 0;
61 if (ti.sign = (ti.a < 0)) // ���Ǹ�������������ʱ��������λ��
62 ti.a = - ti.a; // ��ʱ������β��������Ϊ��������
63 int_to_real(&ti,tmp); // ����ʱ����ת������ʱʵ����ʽ��
64 }
65
// ȡ�û��ڴ��еij�������ת������ʱʵ����ʽ��
// ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ó�
// ����������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��ʱ������
// ʽ��������ʱ����ֵת������ʱʵ����math/convert.c����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
66 void get_long_int(temp_real * tmp,
67 struct info * info, unsigned short code)
68 {
69 char * addr;
70 temp_int ti;
71
72 addr = ea(info,code); // ȡָ���е���Ч��ֵַ��
73 ti.a = get_fs_long((unsigned long *) addr);
74 ti.b = 0;
75 if (ti.sign = (ti.a < 0)) // ���Ǹ�������������ʱ��������λ��
76 ti.a = - ti.a; // ��ʱ������β��������Ϊ��������
77 int_to_real(&ti,tmp); // ����ʱ����ת������ʱʵ����ʽ��
78 }
79
// ȡ�û��ڴ��е�64λ��������ת������ʱʵ����ʽ��
// ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�ȡ��
// 64λ������������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��
// ʱ������ʽ������ٰ���ʱ����ֵת������ʱʵ����math/convert.c����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
80 void get_longlong_int(temp_real * tmp,
81 struct info * info, unsigned short code)
82 {
83 char * addr;
84 temp_int ti;
85
86 addr = ea(info,code); // ȡָ���е���Ч��ֵַ��
87 ti.a = get_fs_long((unsigned long *) addr); // ȡ�û�64λ��������
88 ti.b = get_fs_long(1 + (unsigned long *) addr);
89 if (ti.sign = (ti.b < 0)) // ���Ǹ�����������ʱ��������λ��
90 __asm__("notl %0 ; notl %1\n\t" // ͬʱȡ����1�ͽ�λ������
91 "addl $1,%0 ; adcl $0,%1"
92 :"=r" (ti.a),"=r" (ti.b)
93 :"" (ti.a),"1" (ti.b));
94 int_to_real(&ti,tmp); // ����ʱ����ת������ʱʵ����ʽ��
95 }
96
// ��һ��64λ����������N����10��
// �������������BCD����ֵת������ʱʵ����ʽ�����С������ǣ�N<<1 + N<<3��
97 #define MUL10(low,high) \
98 __asm__("addl %0,%0 ; adcl %1,%1\n\t" \
99 "movl %0,%%ecx ; movl %1,%%ebx\n\t" \
100 "addl %0,%0 ; adcl %1,%1\n\t" \
101 "addl %0,%0 ; adcl %1,%1\n\t" \
102 "addl %%ecx,%0 ; adcl %%ebx,%1" \
103 :"=a" (low),"=d" (high) \
104 :"" (low),"1" (high):"cx","bx")
105
// 64λ�ӷ���
// ��32λ��������val�ӵ�64λ�� <high,low> �С�
106 #define ADD64(val,low,high) \
107 __asm__("addl %4,%0 ; adcl $0,%1":"=r" (low),"=r" (high) \
108 :"" (low),"1" (high),"r" ((unsigned long) (val)))
109
// ȡ�û��ڴ��е�BCD����ֵ��ת������ʱʵ����ʽ��
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�� BCD��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ 10�ֽ���ӦBCD��ֵ����
// ��1�ֽ����ڷ��ţ���ͬʱת������ʱ������ʽ��������ʱ����ֵת������ʱʵ����
// ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣
110 void get_BCD(temp_real * tmp, struct info * info, unsigned short code)
111 {
112 int k;
113 char * addr;
114 temp_int i;
115 unsigned char c;
116
// ȡ��BCD����ֵ�����ڴ���Ч��ַ��Ȼ������1��BCD���ֽڣ������Чλ����ʼ������
// ��ȡ��BCD����ֵ�ķ���λ����������ʱ�����ķ���λ��Ȼ���9�ֽڵ�BCD��ֵת����
// ��ʱ������ʽ������ٰ���ʱ����ֵת������ʱʵ����
117 addr = ea(info,code); // ȡ��Ч��ַ��
118 addr += 9; // ָ�����һ������10�����ֽڡ�
119 i.sign = 0x80 & get_fs_byte(addr--); // ȡ���з���λ��
120 i.a = i.b = 0;
121 for (k = 0; k < 9; k++) { // ת������ʱ������ʽ��
122 c = get_fs_byte(addr--);
123 MUL10(i.a, i.b);
124 ADD64((c>>4), i.a, i.b);
125 MUL10(i.a, i.b);
126 ADD64((c&0xf), i.a, i.b);
127 }
128 int_to_real(&i,tmp); // ת������ʱʵ����ʽ��
129 }
130
// ���������Զ̣������ȣ�ʵ����ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת���ɶ�ʵ����ʽ���洢����Ч
// ��ַaddr����
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
131 void put_short_real(const temp_real * tmp,
132 struct info * info, unsigned short code)
133 {
134 char * addr;
135 short_real sr;
136
137 addr = ea(info,code); // ȡ��Ч��ַ��
138 verify_area(addr,4); // Ϊ��������֤������ڴ档
139 temp_to_short(tmp,&sr); // ���ת���ɶ�ʵ����ʽ��
140 put_fs_long(sr,(unsigned long *) addr); // �洢���ݵ��û��ڴ�����
141 }
142
// ���������Գ���˫���ȣ�ʵ����ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת���ɳ�ʵ����ʽ�����洢����
// Ч��ַaddr����
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
143 void put_long_real(const temp_real * tmp,
144 struct info * info, unsigned short code)
145 {
146 char * addr;
147 long_real lr;
148
149 addr = ea(info,code); // ȡ��Ч��ַ��
150 verify_area(addr,8); // Ϊ��������֤������ڴ档
151 temp_to_long(tmp,&lr); // ���ת���ɳ�ʵ����ʽ��
152 put_fs_long(lr.a, (unsigned long *) addr); // �洢���ݵ��û��ڴ�����
153 put_fs_long(lr.b, 1 + (unsigned long *) addr);
154 }
155
// ������������ʱʵ����ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ���洢����Ч��ַaddr����
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
156 void put_temp_real(const temp_real * tmp,
157 struct info * info, unsigned short code)
158 {
159 char * addr;
160
161 addr = ea(info,code); // ȡ��Ч��ַ��
162 verify_area(addr,10); // Ϊ��������֤������ڴ档
163 put_fs_long(tmp->a, (unsigned long *) addr); // �洢���ݵ��û��ڴ�����
164 put_fs_long(tmp->b, 1 + (unsigned long *) addr);
165 put_fs_word(tmp->exponent, 4 + (short *) addr);
166 }
167
// ���������Զ�������ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�
// ����������������λ�������������浽�û��ڴ��С�
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
168 void put_short_int(const temp_real * tmp,
169 struct info * info, unsigned short code)
170 {
171 char * addr;
172 temp_int ti;
173
174 addr = ea(info,code); // ȡ��Ч��ַ��
175 real_to_int(tmp,&ti); // ת������ʱ������ʽ��
176 verify_area(addr,2); // ��֤�����洢�ڴ档
177 if (ti.sign) // ���з���λ����ȡ����ֵ��
178 ti.a = -ti.a;
179 put_fs_word(ti.a,(short *) addr); // �洢���û��������С�
180 }
181
// ���������Գ�������ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�
// ����������������λ�������������浽�û��ڴ��С�
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
182 void put_long_int(const temp_real * tmp,
183 struct info * info, unsigned short code)
184 {
185 char * addr;
186 temp_int ti;
187
188 addr = ea(info,code); // ȡ��Ч��ַ��
189 real_to_int(tmp,&ti); // ת������ʱ������ʽ��
190 verify_area(addr,4); // ��֤�����洢�ڴ档
191 if (ti.sign) // ���з���λ����ȡ����ֵ��
192 ti.a = -ti.a;
193 put_fs_long(ti.a,(unsigned long *) addr); // �洢���û��������С�
194 }
195
// ����������64λ������ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�
// ����������������λ�������������浽�û��ڴ��С�
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
196 void put_longlong_int(const temp_real * tmp,
197 struct info * info, unsigned short code)
198 {
199 char * addr;
200 temp_int ti;
201
202 addr = ea(info,code); // ȡ��Ч��ַ��
203 real_to_int(tmp,&ti); // ת������ʱ������ʽ��
204 verify_area(addr,8); // ��֤�洢����
205 if (ti.sign) // ���Ǹ�������ȡ����1��
206 __asm__("notl %0 ; notl %1\n\t"
207 "addl $1,%0 ; adcl $0,%1"
208 :"=r" (ti.a),"=r" (ti.b)
209 :"" (ti.a),"1" (ti.b));
210 put_fs_long(ti.a,(unsigned long *) addr); // �洢���û��������С�
211 put_fs_long(ti.b,1 + (unsigned long *) addr);
212 }
213
// ������<high, low>����10����������rem��
214 #define DIV10(low,high,rem) \
215 __asm__("divl %6 ; xchgl %1,%2 ; divl %6" \
216 :"=d" (rem),"=a" (low),"=b" (high) \
217 :"" (0),"1" (high),"2" (low),"c" (10))
218
// ����������BCD���ʽ���浽�û��������С�
// �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�
// ȡ�ñ���������Ч��ַaddr������֤����10�ֽ�BCD����û��ռ䡣Ȼ�����ʱʵ����ʽ
// �Ľ��ת����BCD���ʽ�����ݲ����浽�û��ڴ��С�����Ǹ�����������ߴ洢�ֽڵ����
// ��Чλ��
// ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣
219 void put_BCD(const temp_real * tmp,struct info * info, unsigned short code)
220 {
221 int k,rem;
222 char * addr;
223 temp_int i;
224 unsigned char c;
225
226 addr = ea(info,code); // ȡ��Ч��ַ��
227 verify_area(addr,10); // ��֤�洢�ռ�������
228 real_to_int(tmp,&i); // ת������ʱ������ʽ��
229 if (i.sign) // ���Ǹ����������÷����ֽ������Чλ��
230 put_fs_byte(0x80, addr+9);
231 else // ��������ֽ�����Ϊ0��
232 put_fs_byte(0, addr+9);
233 for (k = 0; k < 9; k++) { // ��ʱ����ת����BCD�벢���档
234 DIV10(i.a,i.b,rem);
235 c = rem;
236 DIV10(i.a,i.b,rem);
237 c += rem<<4;
238 put_fs_byte(c,addr++);
239 }
240 }
241
1 /*
2 * linux/kernel/math/mul.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * temporary real multiplication routine.
9 */
/*
* ��ʱʵ���˷��ӳ���
*/
10
11 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
12
// ��cָ�봦��16�ֽ�ֵ����1λ����2����
13 static void shift(int * c)
14 {
15 __asm__("movl (%0),%%eax ; addl %%eax,(%0)\n\t"
16 "movl 4(%0),%%eax ; adcl %%eax,4(%0)\n\t"
17 "movl 8(%0),%%eax ; adcl %%eax,8(%0)\n\t"
18 "movl 12(%0),%%eax ; adcl %%eax,12(%0)"
19 ::"r" ((long) c):"ax");
20 }
21
// 2����ʱʵ����ˣ��������cָ�봦��16�ֽڣ���
22 static void mul64(const temp_real * a, const temp_real * b, int * c)
23 {
24 __asm__("movl (%0),%%eax\n\t"
25 "mull (%1)\n\t"
26 "movl %%eax,(%2)\n\t"
27 "movl %%edx,4(%2)\n\t"
28 "movl 4(%0),%%eax\n\t"
29 "mull 4(%1)\n\t"
30 "movl %%eax,8(%2)\n\t"
31 "movl %%edx,12(%2)\n\t"
32 "movl (%0),%%eax\n\t"
33 "mull 4(%1)\n\t"
34 "addl %%eax,4(%2)\n\t"
35 "adcl %%edx,8(%2)\n\t"
36 "adcl $0,12(%2)\n\t"
37 "movl 4(%0),%%eax\n\t"
38 "mull (%1)\n\t"
39 "addl %%eax,4(%2)\n\t"
40 "adcl %%edx,8(%2)\n\t"
41 "adcl $0,12(%2)"
42 ::"b" ((long) a),"c" ((long) b),"D" ((long) c)
43 :"ax","dx");
44 }
45
// ���渡��ָ��FMUL��
// ��ʱʵ��src1 * scr2 �� result����
46 void fmul(const temp_real * src1, const temp_real * src2, temp_real * result)
47 {
48 int i,sign;
49 int tmp[4] = {0,0,0,0};
50
// ����ȷ��������˵ķ��š�����ֵ�������߷���λ���ֵ��Ȼ�����˺��ָ��ֵ�����ʱ
// ָ��ֵ��Ҫ��ӡ���������ָ��ʹ��ƫִ����ʽ���棬��������ָ�����ʱƫ����Ҳ������
// ���Σ������Ҫ����һ��ƫ����ֵ����ʱʵ����ƫ������16383����
51 sign = (src1->exponent ^ src2->exponent) & 0x8000;
52 i = (src1->exponent & 0x7fff) + (src2->exponent & 0x7fff) - 16383 + 1;
// ������ָ������˸�ֵ����ʾ������˺�������硣����ֱ�ӷ��ش����ŵ���ֵ��
// ������ָ������0x7fff����ʾ�������磬��������״̬������쳣��־λ�������ء�
53 if (i<0) {
54 result->exponent = sign;
55 result->a = result->b = 0;
56 return;
57 }
58 if (i>0x7fff) {
59 set_OE();
60 return;
61 }
// �������β����˺�����Ϊ0����Խ��β�����й�����������ƽ��β��ֵ��ʹ��
// �����ЧλΪ1��ͬʱ��Ӧ�ص���ָ��ֵ�����������β����˺�16�ֽڵĽ��β��Ϊ0��
// ��Ҳ����ָ��ֵΪ0��������˽����������ʱʵ������result�С�
62 mul64(src1,src2,tmp);
63 if (tmp[0] || tmp[1] || tmp[2] || tmp[3])
64 while (i && tmp[3] >= 0) {
65 i--;
66 shift(tmp);
67 }
68 else
69 i = 0;
70 result->exponent = i | sign;
71 result->a = tmp[2];
72 result->b = tmp[3];
73 }
74
1 /*
2 * linux/kernel/math/div.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * temporary real division routine.
9 */
10
11 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�
12
// ��ָ��cָ���4�ֽ�����������1λ��
13 static void shift_left(int * c)
14 {
15 __asm__ __volatile__("movl (%0),%%eax ; addl %%eax,(%0)\n\t"
16 "movl 4(%0),%%eax ; adcl %%eax,4(%0)\n\t"
17 "movl 8(%0),%%eax ; adcl %%eax,8(%0)\n\t"
18 "movl 12(%0),%%eax ; adcl %%eax,12(%0)"
19 ::"r" ((long) c):"ax");
20 }
21
// ��ָ��cָ���4�ֽ�����������1λ��
22 static void shift_right(int * c)
23 {
24 __asm__("shrl $1,12(%0) ; rcrl $1,8(%0) ; rcrl $1,4(%0) ; rcrl $1,(%0)"
25 ::"r" ((long) c));
26 }
27
// �������㡣
// 16�ֽڼ������㣬a - b �� a���������Ƿ��н�λ��CF=1������ok������λ��CF=0��
// ��ok = 1������ok=0��
28 static int try_sub(int * a, int * b)
29 {
30 char ok;
31
32 __asm__ __volatile__("movl (%1),%%eax ; subl %%eax,(%2)\n\t"
33 "movl 4(%1),%%eax ; sbbl %%eax,4(%2)\n\t"
34 "movl 8(%1),%%eax ; sbbl %%eax,8(%2)\n\t"
35 "movl 12(%1),%%eax ; sbbl %%eax,12(%2)\n\t"
36 "setae %%al":"=a" (ok):"c" ((long) a),"d" ((long) b));
37 return ok;
38 }
39
// 16�ֽڳ�����
// ���� a /b �� c�����ü���ģ����ֽڳ�����
40 static void div64(int * a, int * b, int * c)
41 {
42 int tmp[4];
43 int i;
44 unsigned int mask = 0;
45
46 c += 4;
47 for (i = 0 ; i<64 ; i++) {
48 if (!(mask >>= 1)) {
49 c--;
50 mask = 0x80000000;
51 }
52 tmp[0] = a[0]; tmp[1] = a[1];
53 tmp[2] = a[2]; tmp[3] = a[3];
54 if (try_sub(b,tmp)) {
55 *c |= mask;
56 a[0] = tmp[0]; a[1] = tmp[1];
57 a[2] = tmp[2]; a[3] = tmp[3];
58 }
59 shift_right(b);
60 }
61 }
62
// ���渡��ָ��FDIV��
63 void fdiv(const temp_real * src1, const temp_real * src2, temp_real * result)
64 {
65 int i,sign;
66 int a[4],b[4],tmp[4] = {0,0,0,0};
67
68 sign = (src1->exponent ^ src2->exponent) & 0x8000;
69 if (!(src2->a || src2->b)) {
70 set_ZE();
71 return;
72 }
73 i = (src1->exponent & 0x7fff) - (src2->exponent & 0x7fff) + 16383;
74 if (i<0) {
75 set_UE();
76 result->exponent = sign;
77 result->a = result->b = 0;
78 return;
79 }
80 a[0] = a[1] = 0;
81 a[2] = src1->a;
82 a[3] = src1->b;
83 b[0] = b[1] = 0;
84 b[2] = src2->a;
85 b[3] = src2->b;
86 while (b[3] >= 0) {
87 i++;
88 shift_left(b);
89 }
90 div64(a,b,tmp);
91 if (tmp[0] || tmp[1] || tmp[2] || tmp[3]) {
92 while (i && tmp[3] >= 0) {
93 i--;
94 shift_left(tmp);
95 }
96 if (tmp[3] >= 0)
97 set_DE();
98 } else
99 i = 0;
100 if (i>0x7fff) {
101 set_OE();
102 return;
103 }
104 if (tmp[0] || tmp[1])
105 set_PE();
106 result->exponent = i | sign;
107 result->a = tmp[2];
108 result->b = tmp[3];
109 }
110
1 /*
2 * linux/fs/buffer.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * 'buffer.c' implements the buffer-cache functions. Race-conditions have
9 * been avoided by NEVER letting a interrupt change a buffer (except for the
10 * data, of course), but instead letting the caller do it. NOTE! As interrupts
11 * can wake up a caller, some cli-sti sequences are needed to check for
12 * sleep-on-calls. These should be extremely quick, though (I hope).
13 */
/*
* 'buffer.c'����ʵ�ֻ��������ٻ��湦�ܡ�ͨ�������жϴ������̸ı仺�����������õ�
* ������ִ�У������˾�����������Ȼ���ı��������⣩��ע�⣡�����жϿ��Ի���һ����
* ���ߣ���˾���Ҫ�����ж�ָ�cli-sti��������������ڵ��ö�˯�ߡ�����Ҫ�dz��ؿ�
* ����ϣ������������
*/
14
15 /*
16 * NOTE! There is one discordant note here: checking floppies for
17 * disk change. This is where it fits best, I think, as it should
18 * invalidate changed floppy-disk-caches.
19 */
/*
* ע�⣡��һ������Ӧ�����������������Ƿ�����������������Ƿ���
* �ó�����õĵط��ˣ���Ϊ����Ҫʹ�Ѹ������̻���ʧЧ��
*/
20
21 #include <stdarg.h> // ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��
// ����(va_list)��������(va_start, va_arg��va_end)������
// vsprintf��vprintf��vfprintf������
22
23 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE����ѡ�
24 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
25 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
26 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ����ꡣ
27 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
28
// ����end���ɱ���ʱ�����ӳ���ld���ɣ����ڱ����ں˴����ĩ�ˣ���ָ���ں�ģ��ĩ��
// λ�ã��μ�����!δ�ҵ�����Դ����Ҳ���Դӱ����ں�ʱ���ɵ� System.map�ļ��в����������������
// �����ٻ�������ʼ���ں˴���ĩ��λ�á�
// ��33���ϵ�buffer_wait�����ǵȴ����л�����˯�ߵ��������ͷָ�롣���뻺���ͷ
// ���ṹ��b_waitָ������ò�ͬ������������һ����������������ϵͳȱ�����ÿ��л�
// ���ʱ����ǰ����ͻᱻ���ӵ�buffer_wait˯�ߵȴ������С���b_wait����ר�Ź��ȴ�
// ָ������飨��b_wait��Ӧ�Ļ���飩������ʹ�õĵȴ�����ͷָ�롣
29 extern int end;
30 struct buffer_head * start_buffer = (struct buffer_head *) &end;
31 struct buffer_head * hash_table[NR_HASH]; // NR_HASH = 307�
32 static struct buffer_head * free_list; // ���л��������ͷָ�롣
33 static struct task_struct * buffer_wait = NULL; // �ȴ����л�����˯�ߵ�������С�
// ���涨��ϵͳ�������к��еĻ������������NR_BUFFERS��һ��������linux/fs.hͷ
// �ļ���48�еĺ꣬��ֵ���DZ�����nr_buffers��������fs.h�ļ���172������Ϊȫ�ֱ�����
// ��д����ͨ������һ�������ƣ�Linus������д������Ϊ�����������д�����������ر�ʾ
// nr_buffers��һ�����ں˳�ʼ��֮���ٸı�ġ��������������ڳ�ʼ������buffer_init()
// �б����ã���371�У���
34 int NR_BUFFERS = 0; // ϵͳ���л���������
35
//// �ȴ�ָ������������
// ���ָ���Ļ����bh�Ѿ��������ý��̲����жϵ�˯���ڸû����ĵȴ�����b_wait�С�
// �ڻ�������ʱ����ȴ������ϵ����н��̽������ѡ���Ȼ���ڹر��жϣ�cli��֮��ȥ˯
// �ߵģ���������������Ӱ����������������������Ӧ�жϡ���Ϊÿ�����̶����Լ���TSS��
// �б����˱�־�Ĵ���EFLAGS��ֵ�������ڽ����л�ʱCPU�е�ǰEFLAGS��ֵҲ��֮�ı䡣
// ʹ��sleep_on()����˯��״̬�Ľ�����Ҫ��wake_up()��ȷ�ػ��ѡ�
36 static inline void wait_on_buffer(struct buffer_head * bh)
37 {
38 cli(); // ���жϡ�
39 while (bh->b_lock) // ����ѱ���������̽���˯�ߣ��ȴ��������
40 sleep_on(&bh->b_wait);
41 sti(); // ���жϡ�
42 }
43
//// �豸����ͬ����
// ͬ���豸���ڴ���ٻ��������ݡ����У�sync_inodes()������inode.c��59�С�
44 int sys_sync(void)
45 {
46 int i;
47 struct buffer_head * bh;
48
// ���ȵ���i�ڵ�ͬ�����������ڴ�i�ڵ���������Ĺ���i�ڵ�д����ٻ����С�Ȼ��
// ɨ�����и��ٻ����������ѱ��ĵĻ�������д����������������д�����У�����
// ���ٻ����е��������豸�е�ͬ����
49 sync_inodes(); /* write out inodes into buffers */
50 bh = start_buffer; // bhָ������ʼ����
51 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
52 wait_on_buffer(bh); // �ȴ�����������������������Ļ�����
53 if (bh->b_dirt)
54 ll_rw_block(WRITE,bh); // ����д�豸������
55 }
56 return 0;
57 }
58
//// ��ָ���豸���и��ٻ����������豸�����ݵ�ͬ��������
// �ú��������������ٻ����������л���顣����ָ���豸dev�Ļ���飬���������ѱ���
// ����д�����У�ͬ����������Ȼ����ڴ���i�ڵ������д����ٻ����С�֮���ٶ�ָ����
// ��devִ��һ����������ͬ��д�̲�����
59 int sync_dev(int dev)
60 {
61 int i;
62 struct buffer_head * bh;
63
// ���ȶԲ���ָ�����豸ִ������ͬ�����������豸�ϵ���������ٻ������е�����ͬ����
// ������ɨ����ٻ����������л���飬��ָ���豸dev�Ļ���飬�ȼ�����Ƿ��ѱ�������
// ���ѱ�������˯�ߵȴ��������Ȼ�����ж�һ�θû�����Ƿ���ָ���豸�Ļ���鲢��
// ���Ĺ���b_dirt��־��λ�������ǾͶ���ִ��д�̲�������Ϊ������˯���ڼ�û����
// �п����ѱ��ͷŻ��߱�Ų�����ã������ڼ���ִ��ǰ��Ҫ�ٴ��ж�һ�¸û�����Ƿ���
// ָ���豸�Ļ���飬
64 bh = start_buffer; // bhָ������ʼ����
65 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
66 if (bh->b_dev != dev) // �����豸dev�Ļ�����������
67 continue;
68 wait_on_buffer(bh); // �ȴ�����������������������Ļ�����
69 if (bh->b_dev == dev && bh->b_dirt)
70 ll_rw_block(WRITE,bh);
71 }
// �ٽ�i�ڵ�����д����ٻ��塣��i�ڵ��inode_table�е�inode�뻺���е���Ϣͬ����
72 sync_inodes();
// Ȼ���ڸ��ٻ����е����ݸ���֮���ٰ��������豸�е�����ͬ���������������ͬ������
// ��Ϊ������ں�ִ��Ч�ʡ���һ�黺����ͬ�������������ں������ࡰ��顱��ɾ���ʹ��
// i�ڵ��ͬ�������ܹ���Чִ�С����λ�����ͬ�����������Щ����i�ڵ�ͬ���������ֱ�
// ��Ļ�������豸������ͬ����
73 bh = start_buffer;
74 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
75 if (bh->b_dev != dev)
76 continue;
77 wait_on_buffer(bh);
78 if (bh->b_dev == dev && bh->b_dirt)
79 ll_rw_block(WRITE,bh);
80 }
81 return 0;
82 }
83
//// ʹָ���豸�ڸ��ٻ������е�������Ч��
// ɨ����ٻ����������л���顣��ָ���豸�Ļ���鸴λ����Ч(����)��־�����ı�־��
84 void inline invalidate_buffers(int dev)
85 {
86 int i;
87 struct buffer_head * bh;
88
89 bh = start_buffer;
90 for (i=0 ; i<NR_BUFFERS ; i++,bh++) {
91 if (bh->b_dev != dev) // �������ָ���豸�Ļ���飬��
92 continue; // ����ɨ����һ�顣
93 wait_on_buffer(bh); // �ȴ��û���������������ѱ���������
// ���ڽ���ִ�й�˯�ߵȴ���������Ҫ���ж�һ�»������Ƿ���ָ���豸�ġ�
94 if (bh->b_dev == dev)
95 bh->b_uptodate = bh->b_dirt = 0;
96 }
97 }
98
99 /*
100 * This routine checks whether a floppy has been changed, and
101 * invalidates all buffer-cache-entries in that case. This
102 * is a relatively slow routine, so we have to try to minimize using
103 * it. Thus it is called only upon a 'mount' or 'open'. This
104 * is the best way of combining speed and utility, I think.
105 * People changing diskettes in the middle of an operation deserve
106 * to loose :-)
107 *
108 * NOTE! Although currently this is only for floppies, the idea is
109 * that any additional removable block-device will use this routine,
110 * and that mount/open needn't know that floppies/whatever are
111 * special.
112 */
/*
* ���ӳ�����һ�������Ƿ��ѱ�����������Ѿ�������ʹ���ٻ������������
* ��Ӧ�����л�������Ч�����ӳ��������˵��������������Ҫ������ʹ������
* ���Խ���ִ��'mount'��'open'ʱ�ŵ��������������ǽ��ٶȺ�ʵ�������ϵ�
* ��÷��������ڲ��������и������̣��ͻᵼ�����ݵĶ�ʧ�����Ǿ�����ȡJ��
*
* ע�⣡����Ŀǰ���ӳ�����������̣��Ժ��κο��ƶ����ʵĿ��豸����ʹ�ø�
* ����mount/open��������Ҫ֪�������̻�������ʲô������ʡ�
*/
//// �������Ƿ����������Ѹ�����ʹ��Ӧ���ٻ�������Ч��
113 void check_disk_change(int dev)
114 {
115 int i;
116
// ���ȼ��һ���Dz��������豸����Ϊ���ڽ�֧�����̿��ƶ����ʡ�����������˳���Ȼ��
// ���������Ƿ��Ѹ��������û�����˳���floppy_change()��blk_drv/floppy.c��139�С�
117 if (MAJOR(dev) != 2)
118 return;
119 if (!floppy_change(dev & 0x03))
120 return;
// �����Ѿ������������ͷŶ�Ӧ�豸��i�ڵ�λͼ������λͼ��ռ�ĸ��ٻ���������ʹ��
// �豸��i�ڵ�����ݿ���Ϣ��ռ��ĸ��ٻ������Ч��
121 for (i=0 ; i<NR_SUPER ; i++)
122 if (super_block[i].s_dev == dev)
123 put_super(super_block[i].s_dev);
124 invalidate_inodes(dev);
125 invalidate_buffers(dev);
126 }
127
// �������д�����hash��ɢ�У����������hash����ļ���ꡣ
// hash������Ҫ�����Ǽ��ٲ��ұȽ�Ԫ�������ѵ�ʱ�䡣ͨ����Ԫ�صĴ洢λ����ؼ���֮��
// ����һ����Ӧ��ϵ��hash�����������ǾͿ���ֱ��ͨ�������������̲�ѯ��ָ����Ԫ�ء���
// ��hash������ָ��������Ҫ�Ǿ���ȷ��ɢ�е��κ�������ĸ��ʻ�����ȡ����������ķ���
// �ж��֣�����Linux 0.12��Ҫ�����˹ؼ��ֳ�������������Ϊ����Ѱ�ҵĻ����������������
// ���豸��dev�ͻ�����block�������Ƶ�hash�����϶���Ҫ�����������ؼ�ֵ����������
// �ؼ��ֵ�������ֻ�Ǽ���ؼ�ֵ��һ�ַ������ٶԹؼ�ֵ����MOD����Ϳ��Ա�֤��������
// ��õ���ֵ�����ں��������Χ�ڡ�
128 #define _hashfn(dev,block) (((unsigned)(dev^block))%NR_HASH)
129 #define hash(dev,block) hash_table[_hashfn(dev,block)]
130
//// ��hash���кͿ��л��������������顣
// hash������˫�������ṹ�����л���������˫��ѭ�������ṹ��
131 static inline void remove_from_queues(struct buffer_head * bh)
132 {
133 /* remove from hash-queue */
/* ��hash�������Ƴ������ */
134 if (bh->b_next)
135 bh->b_next->b_prev = bh->b_prev;
136 if (bh->b_prev)
137 bh->b_prev->b_next = bh->b_next;
// ����û������Ǹö��е�ͷһ���飬����hash���Ķ�Ӧ��ָ�����е���һ����������
138 if (hash(bh->b_dev,bh->b_blocknr) == bh)
139 hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
140 /* remove from free list */
/* �ӿ��л��������Ƴ������ */
141 if (!(bh->b_prev_free) || !(bh->b_next_free))
142 panic("Free block list corrupted");
143 bh->b_prev_free->b_next_free = bh->b_next_free;
144 bh->b_next_free->b_prev_free = bh->b_prev_free;
// �����������ͷָ��������������ָ����һ��������
145 if (free_list == bh)
146 free_list = bh->b_next_free;
147 }
148
//// �����������������β����ͬʱ����hash�����С�
149 static inline void insert_into_queues(struct buffer_head * bh)
150 {
151 /* put at end of free list */
/* ���ڿ�������ĩβ�� */
152 bh->b_next_free = free_list;
153 bh->b_prev_free = free_list->b_prev_free;
154 free_list->b_prev_free->b_next_free = bh;
155 free_list->b_prev_free = bh;
156 /* put the buffer in new hash-queue if it has a device */
/* ����û�����Ӧһ���豸�����������hash������ */
// ��ע�hash��ij���1�β�����ʱ��hash()����ֵ�϶�ΪNULL����˴�ʱ��161����
// �õ���bh->b_next�϶���NULL�����Ե�163����Ӧ����bh->b_next��ΪNULLʱ���ܸ�
// b_prev��bhֵ������163��ǰӦ�������жϡ�if (bh->b_next)�����ô���0.96���
// �ű�������
157 bh->b_prev = NULL;
158 bh->b_next = NULL;
159 if (!bh->b_dev)
160 return;
161 bh->b_next = hash(bh->b_dev,bh->b_blocknr);
162 hash(bh->b_dev,bh->b_blocknr) = bh;
163 bh->b_next->b_prev = bh; // �˾�ǰӦ���ӡ�if (bh->b_next)���жϡ�
164 }
165
//// ����hash���ڸ��ٻ�����Ѱ�Ҹ����豸��ָ����ŵĻ������顣
// ����ҵ��ػ��������ָ�룬����NULL��
166 static struct buffer_head * find_buffer(int dev, int block)
167 {
168 struct buffer_head * tmp;
169
// ����hash����Ѱ��ָ���豸�źͿ�ŵĻ���顣
170 for (tmp = hash(dev,block) ; tmp != NULL ; tmp = tmp->b_next)
171 if (tmp->b_dev==dev && tmp->b_blocknr==block)
172 return tmp;
173 return NULL;
174 }
175
176 /*
177 * Why like this, I hear you say... The reason is race-conditions.
178 * As we don't lock buffers (unless we are readint them, that is),
179 * something might happen to it while we sleep (ie a read-error
180 * will force it bad). This shouldn't really happen currently, but
181 * the code is ready.
182 */
/*
* ����Ϊʲô���������ӵģ�����������... ԭ���Ǿ�����������������û�ж�
* ����������������������ڶ�ȡ�����е����ݣ�����ô�����ǣ����̣�˯��ʱ
* �������ܻᷢ��һЩ���⣨����һ���������¸û�����������Ŀǰ
* �������ʵ�����Dz��ᷢ���ģ��������Ĵ����Ѿ������ˡ�
*/
//// ����hash���ڸ��ٻ�������Ѱ��ָ���Ļ���顣���ҵ���Ըû�������������ؿ�ͷָ�롣
183 struct buffer_head * get_hash_table(int dev, int block)
184 {
185 struct buffer_head * bh;
186
187 for (;;) {
// �ڸ��ٻ�����Ѱ�Ҹ����豸��ָ����Ļ������飬���û���ҵ���NULL���˳���
188 if (!(bh=find_buffer(dev,block)))
189 return NULL;
// �Ըû�����������ü��������ȴ��û�������������ѱ������������ھ�����˯��״̬��
// ����б�Ҫ����֤�û�������ȷ�ԣ������ػ����ͷָ�롣
190 bh->b_count++;
191 wait_on_buffer(bh);
192 if (bh->b_dev == dev && bh->b_blocknr == block)
193 return bh;
// �����˯��ʱ�û�����������豸�Ż��ŷ����˸ı䣬�������������ü���������Ѱ�ҡ�
194 bh->b_count--;
195 }
196 }
197
198 /*
199 * Ok, this is getblk, and it isn't very clear, again to hinder
200 * race-conditions. Most of the code is seldom used, (ie repeating),
201 * so it should be much more efficient than it looks.
202 *
203 * The algoritm is changed: hopefully better, and an elusive bug removed.
204 */
/*
* OK��������getblk�������ú������������Ǻ�������ͬ��Ҳ����ΪҪ����
* �����������⡣���дִ�������õ���(�����ظ��������)�������Ӧ��
* �ȿ���ȥ��������Ч�öࡣ
*
* �㷨�Ѿ����˸ı䣺ϣ���ܸ��ã�����һ��������ĥ�Ĵ����Ѿ�ȥ����
*/
// ���������ͬʱ�жϻ��������ı�־��������־�����Ҷ����ı�־��Ȩ��Ҫ��������־
// ��
205 #define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
//// ȡ���ٻ�����ָ���Ļ���顣
// ���ָ�����豸�źͿ�ţ��Ļ������Ƿ��Ѿ��ڸ��ٻ����С����ָ�����Ѿ��ڸ��ٻ����У�
// �ض�Ӧ������ͷָ���˳���������ڣ�����Ҫ�ڸ��ٻ���������һ����Ӧ�豸�źͿ�ŵ�
// ���������Ӧ������ͷָ�롣
206 struct buffer_head * getblk(int dev,int block)
207 {
208 struct buffer_head * tmp, * bh;
209
210 repeat:
// ����hash�������ָ�����Ѿ��ڸ��ٻ����У��ض�Ӧ������ͷָ�룬�˳���
211 if (bh = get_hash_table(dev,block))
212 return bh;
// ɨ��������ݿ�������Ѱ�ҿ��л�������
// ������tmpָ����������ĵ�һ�����л�����ͷ��
213 tmp = free_list;
214 do {
// ����û���������ʹ�ã����ü���������0���������ɨ����һ�����b_count=0�Ŀ飬
// �����ٻ����е�ǰû�����õĿ鲻һ�����Ǹɾ��ģ�b_dirt=0����û�������ģ�b_lock=0����
// ��ˣ����ǻ�����Ҫ����������жϺ�ѡ�����統һ�������д��һ�����ݺ���ͷ��ˣ�
// ���Ǹÿ�b_count = 0����b_lock������0����һ������ִ�� breada()Ԥ��������ʱ��ֻҪ
// ll_rw_block()����������ͻ�ݼ�b_count������ʱʵ����Ӳ�̷��ʲ������ܻ��ڽ��У�
// ��˴�ʱb_lock=1����b_count=0��
215 if (tmp->b_count)
216 continue;
// �������ͷָ��bhΪ�գ�����tmp��ָ����ͷ�ı�־(�ġ�����)Ȩ��С��bhͷ��־��Ȩ
// �أ�����bhָ��tmp�����ͷ�� �����tmp�����ͷ����������û����Ҳû��������
// ־��λ����˵����Ϊָ���豸�ϵĿ�ȡ�ö�Ӧ�ĸ��ٻ���飬���˳�ѭ�����������Ǿͼ���
// ִ�б�ѭ���������ܷ��ҵ�һ��BADNESS()��С�Ļ���졣
217 if (!bh || BADNESS(tmp)<BADNESS(bh)) {
218 bh = tmp;
219 if (!BADNESS(tmp))
220 break;
221 }
222 /* and repeat until we find something good */ /* �ظ�����ֱ���ҵ��ʺϵĻ���� */
223 } while ((tmp = tmp->b_next_free) != free_list);
// ���ѭ����鷢�����л���鶼���ڱ�ʹ�ã����л�����ͷ�����ü�����>0���У���˯��
// �ȴ��п��л������á����п��л�������ʱ�����̻ᱻ��ȷ�ػ��ѡ�Ȼ�����Ǿ���ת��
// ������ʼ�����²��ҿ��л���顣
224 if (!bh) {
225 sleep_on(&buffer_wait);
226 goto repeat; // ��ת��210�С�
227 }
// ִ�е����˵�������Ѿ��ҵ���һ���Ƚ��ʺϵĿ��л�����ˡ������ȵȴ��û���������
//������ѱ������Ļ��������������˯�߽θû������ֱ���������ʹ�õĻ���ֻ���ظ�����
// Ѱ�ҹ��̡�
228 wait_on_buffer(bh);
229 if (bh->b_count) // �ֱ�ռ�ã���
230 goto repeat;
// ����û������ѱ��ģ�������д�̣����ٴεȴ�������������ͬ���أ����û������ֱ�
// ��������ʹ�õĻ���ֻ�����ظ�����Ѱ�ҹ��̡�
231 while (bh->b_dirt) {
232 sync_dev(bh->b_dev);
233 wait_on_buffer(bh);
234 if (bh->b_count) // �ֱ�ռ�ã���
235 goto repeat;
236 }
237 /* NOTE!! While we slept waiting for this block, somebody else might */
238 /* already have added "this" block to the cache. check it */
/* ע�⣡��������Ϊ�˵ȴ��û�����˯��ʱ���������̿����Ѿ����û���� */
* ��������ٻ����У���������ҲҪ�Դ˽��м�顣*/
// �ڸ��ٻ���hash���м��ָ���豸�Ϳ�Ļ�����Ƿ������˯��֮���Ѿ��������ȥ�����
// �ǵĻ������ٴ��ظ�����Ѱ�ҹ��̡�
239 if (find_buffer(dev,block))
240 goto repeat;
241 /* OK, FINALLY we know that this buffer is the only one of it's kind, */
242 /* and that it's unused (b_count=0), unlocked (b_lock=0), and clean */
/* OK����������֪���û������ָ��������Ψһһ�飬����Ŀǰ��û�б�ռ�� */
/* (b_count=0)��Ҳδ������(b_lock=0)�������Ǹɾ��ģ�δ���ĵģ�*/
// ����������ռ�ô˻���顣�����ü���Ϊ1����λ�ı�־����Ч(����)��־��
243 bh->b_count=1;
244 bh->b_dirt=0;
245 bh->b_uptodate=0;
// ��hash���кͿ��п��������Ƴ��û�����ͷ���øû���������ָ���豸�����ϵ�ָ���顣
// Ȼ����ݴ��µ��豸�źͿ�����²������������hash������λ�ô��������շ��ػ���
// ͷָ�롣
246 remove_from_queues(bh);
247 bh->b_dev=dev;
248 bh->b_blocknr=block;
249 insert_into_queues(bh);
250 return bh;
251 }
252
//// �ͷ�ָ������顣
// �ȴ��û���������Ȼ�����ü����ݼ�1������ȷ�ػ��ѵȴ����л����Ľ��̡�
253 void brelse(struct buffer_head * buf)
254 {
255 if (!buf) // �������ͷָ����Ч�ء�
256 return;
257 wait_on_buffer(buf);
258 if (!(buf->b_count--))
259 panic("Trying to free free buffer");
260 wake_up(&buffer_wait);
261 }
262
263 /*
264 * bread() reads a specified block and returns the buffer that contains
265 * it. It returns NULL if the block was unreadable.
266 */
/*
* ���豸�϶�ȡָ�������ݿ鲢���غ������ݵĻ����������ָ���Ŀ鲻����
* ��NULL��
*/
//// ���豸�϶�ȡ���ݿ顣
// �ú�������ָ�����豸��dev�����ݿ��block�������ڸ��ٻ�����������һ�黺��顣
// ����û�������Ѿ���������Ч�����ݾ�ֱ�ӷ��ظû����ָ�룬����ʹ��豸�ж�ȡ
// ָ�������ݿ鵽�û�����в����ػ����ָ�롣
267 struct buffer_head * bread(int dev,int block)
268 {
269 struct buffer_head * bh;
270
// �ڸ��ٻ�����������һ�黺��顣�������ֵ��NULL�����ʾ�ں˳�����ͣ����Ȼ������
// �ж������Ƿ����п������ݡ� ����û��������������Ч�ģ��Ѹ��µģ�����ֱ��ʹ�ã�
// �ء�
271 if (!(bh=getblk(dev,block)))
272 panic("bread: getblk returned NULL\n");
273 if (bh->b_uptodate)
274 return bh;
// �������Ǿ͵��õײ���豸��дll_rw_block()�������������豸������Ȼ��ȴ�ָ��
// ���ݿ鱻���룬���ȴ���������������˯������֮������û������Ѹ��£��ػ���
// ��ͷָ�룬�˳�������������豸����ʧ�ܣ������ͷŸû�����������NULL���˳���
275 ll_rw_block(READ,bh);
276 wait_on_buffer(bh);
277 if (bh->b_uptodate)
278 return bh;
279 brelse(bh);
280 return NULL;
281 }
282
//// �����ڴ�顣
// ��from��ַ����һ�飨1024�ֽڣ����ݵ�toλ�á�
283 #define COPYBLK(from,to) \
284 __asm__("cld\n\t" \
285 "rep\n\t" \
286 "movsl\n\t" \
287 ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
288 :"cx","di","si")
289
290 /*
291 * bread_page reads four buffers into memory at the desired address. It's
292 * a function of its own, as there is some speed to be got by reading them
293 * all at the same time, not waiting for one to be read, and then another
294 * etc.
295 */
/*
* bread_pageһ�ζ��ĸ���������ݶ����ڴ�ָ���ĵ�ַ��������һ�������ĺ�����
* ��Ϊͬʱ��ȡ�Ŀ���Ի���ٶ��ϵĺô������õ��Ŷ�һ�飬�ٶ�һ���ˡ�
*/
//// ���豸��һ��ҳ�棨4������飩�����ݵ�ָ���ڴ��ַ����
// ����address�DZ���ҳ�����ݵĵ�ַ��dev��ָ�����豸�ţ�b[4]�Ǻ���4���豸���ݿ��
// �����顣�ú���������mm/memory.c�ļ���do_no_page()�����У���386�У���
296 void bread_page(unsigned long address,int dev,int b[4])
297 {
298 struct buffer_head * bh[4];
299 int i;
300
// �ú���ѭ��ִ��4�Σ����ݷ�������b[]�е�4����Ŵ��豸dev�ж�ȡһҳ���ݷŵ�ָ��
// �ڴ�λ�� address���� ���ڲ���b[i]��������Ч��ţ��������ȴӸ��ٻ�����ȡָ���豸
// �Ϳ�ŵĻ���顣����������������Ч��δ���£���������豸������豸�϶�ȡ��Ӧ��
// �ݿ顣����b[i]��Ч�Ŀ������ȥ�����ˡ���˱�������ʵ���Ը���ָ����b[]�еĿ��
// �����ȡ1��4�����ݿ顣
301 for (i=0 ; i<4 ; i++)
302 if (b[i]) { // ���������
303 if (bh[i] = getblk(dev,b[i]))
304 if (!bh[i]->b_uptodate)
305 ll_rw_block(READ,bh[i]);
306 } else
307 bh[i] = NULL;
// ���4��������ϵ�����˳���Ƶ�ָ����ַ�����ڽ��и��ƣ�ʹ�ã������֮ǰ����
// ��Ҫ˯�ߵȴ��������������������Ļ��������⣬��Ϊ����˯�߹��ˣ��������ǻ���Ҫ
// �ڸ���֮ǰ�ټ��һ�»�����е������Ƿ�����Ч�ġ�����������ǻ���Ҫ�ͷŻ���顣
308 for (i=0 ; i<4 ; i++,address += BLOCK_SIZE)
309 if (bh[i]) {
310 wait_on_buffer(bh[i]); // �ȴ���������(���������Ļ�)��
311 if (bh[i]->b_uptodate) // ���������������Ч�Ļ����ơ�
312 COPYBLK((unsigned long) bh[i]->b_data,address);
313 brelse(bh[i]); // �ͷŸû�������
314 }
315 }
316
317 /*
318 * Ok, breada can be used as bread, but additionally to mark other
319 * blocks for reading as well. End the argument list with a negative
320 * number.
321 */
/*
* OK��breada������breadһ��ʹ�ã���������Ԥ��һЩ�顣�ú��������б�
* ��Ҫʹ��һ�����������������б��Ľ�����
*/
//// ��ָ���豸��ȡָ����һЩ�顣
// �������������ɱ䣬��һϵ��ָ���Ŀ�š��ɹ�ʱ���ص�1��Ļ����ͷָ�룬����
// NULL��
322 struct buffer_head * breada(int dev,int first, ...)
323 {
324 va_list args;
325 struct buffer_head * bh, *tmp;
326
// ����ȡ�ɱ�������е�1����������ţ������ŴӸ��ٻ�������ȡָ���豸�Ϳ�ŵĻ���
// �顣����û����������Ч�����±�־δ��λ���������豸���ݿ�����
327 va_start(args,first);
328 if (!(bh=getblk(dev,first)))
329 panic("bread: getblk returned NULL\n");
330 if (!bh->b_uptodate)
331 ll_rw_block(READ,bh);
// Ȼ��˳��ȡ�ɱ������������Ԥ����ţ�����������ͬ���������������á�ע�⣬336����
// ��һ��bug�����е�bhӦ����tmp�����bugֱ����0.96����ں˴����вű�����������
// ���⣬��Ϊ������Ԥ���������ݿ飬ֻ��������ٻ��������������Ͼ�ʹ�ã����Ե�337
// �������Ҫ�������ü����ݼ��ͷŵ��ÿ飨��Ϊgetblk()���������ӻ�������ü���ֵ����
332 while ((first=va_arg(args,int))>=0) {
333 tmp=getblk(dev,first);
334 if (tmp) {
335 if (!tmp->b_uptodate)
336 ll_rw_block(READA,bh); // bh Ӧ����tmp��
337 tmp->b_count--; // ��ʱ�ͷŵ���Ԥ���顣
338 }
339 }
// ��ʱ�ɱ�����������в���������ϡ����ǵȴ���1������������������ѱ����������ڵ�
// ���˳�֮�������������������Ȼ��Ч���ػ�����ͷָ���˳��������ͷŸû���������
// NULL���˳���
340 va_end(args);
341 wait_on_buffer(bh);
342 if (bh->b_uptodate)
343 return bh;
344 brelse(bh);
345 return (NULL);
346 }
347
//// ��������ʼ��������
// ����buffer_end�ǻ������ڴ�ĩ�ˡ����ھ���16MB�ڴ��ϵͳ��������ĩ�˱�����Ϊ4MB��
// ������8MB�ڴ��ϵͳ��������ĩ�˱�����Ϊ2MB���ú����ӻ�������ʼλ��start_buffer
// ���ͻ�����ĩ��buffer_end���ֱ�ͬʱ���ã���ʼ���������ͷ�ṹ�Ͷ�Ӧ�����ݿ顣ֱ��
// �������������ڴ汻������ϡ��μ������б�ǰ���ʾ��ͼ��
348 void buffer_init(long buffer_end)
349 {
350 struct buffer_head * h = start_buffer;
351 void * b;
352 int i;
353
// ���ȸ��ݲ����ṩ�Ļ������߶�λ��ȷ��ʵ�ʻ������߶�λ��b������������߶˵���1Mb��
// ����Ϊ��640KB - 1MB����ʾ�ڴ�� BIOSռ�ã�����ʵ�ʿ��û������ڴ�߶�λ��Ӧ����
// 640KB���������ڴ�߶�һ������1MB��
354 if (buffer_end == 1<<20)
355 b = (void *) (640*1024);
356 else
357 b = (void *) buffer_end;
// ��δ������ڳ�ʼ�����������������л����ѭ������������ȡϵͳ�л������Ŀ��������
// �����Ǵӻ������߶˿�ʼ����1KB��С�Ļ���飬���ͬʱ�ڻ������Ͷ˽��������û����
// �Ľṹbuffer_head��������Щbuffer_head���˫��������
// h��ָ��ͷ�ṹ��ָ�룬��h+1��ָ���ڴ��ַ��������һ������ͷ��ַ��Ҳ����˵��
// ָ��h����ͷ��ĩ���⡣Ϊ�˱�֤���㹻���ȵ��ڴ����洢һ������ͷ�ṹ����Ҫb��ָ��
// ���ڴ���ַ >= h����ͷ��ĩ�ˣ���Ҫ�� >= h+1��
358 while ( (b -= BLOCK_SIZE) >= ((void *) (h+1)) ) {
359 h->b_dev = 0; // ʹ�øû������豸�š�
360 h->b_dirt = 0; // ���־����������ı�־��
361 h->b_count = 0; // ��������ü�����
362 h->b_lock = 0; // �����������־��
363 h->b_uptodate = 0; // �������±�־�����������Ч��־����
364 h->b_wait = NULL; // ָ��ȴ��û��������Ľ��̡�
365 h->b_next = NULL; // ָ�������ͬhashֵ����һ������ͷ��
366 h->b_prev = NULL; // ָ�������ͬhashֵ��ǰһ������ͷ��
367 h->b_data = (char *) b; // ָ���Ӧ��������ݿ飨1024�ֽڣ���
368 h->b_prev_free = h-1; // ָ��������ǰһ�
369 h->b_next_free = h+1; // ָ����������һ�
370 h++; // hָ����һ�»���ͷλ�á�
371 NR_BUFFERS++; // �����������ۼӡ�
372 if (b == (void *) 0x100000) // ��b�ݼ�������1MB��������384KB��
373 b = (void *) 0xA0000; // ��bָ���ַ0xA0000(640KB)����
374 }
375 h--; // ��hָ�����һ����Ч�����ͷ��
376 free_list = start_buffer; // �ÿ�������ͷָ��ͷһ������顣
377 free_list->b_prev_free = h; // ����ͷ��b_prev_freeָ��ǰһ������һ���
378 h->b_next_free = free_list; // h����һ��ָ��ָ���һ��γ�һ��������
// ����ʼ��hash������ϣ����ɢ�б������ñ�������ָ��ΪNULL��
379 for (i=0;i<NR_HASH;i++)
380 hash_table[i]=NULL;
381 }
382
1 /*
2 * linux/fs/bitmap.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /* bitmap.c contains the code that handles the inode and block bitmaps */
/* bitmap.c�����д���i�ڵ�ʹ��̿�λͼ�Ĵ��� */
8 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
9 // ����ʹ�������е�memset()������
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݡ�
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12
//// ��ָ����ַ��addr������һ��1024�ֽ��ڴ����㡣
// ���룺eax = 0��ecx = �Գ���Ϊ��λ�����ݿ鳤�ȣ�BLOCK_SIZE/4����edi = ָ����ʼ��
// ַaddr��
13 #define clear_block(addr) \
14 __asm__("cld\n\t" \ // �巽��λ��
15 "rep\n\t" \ // �ظ�ִ�д洢���ݣ�0����
16 "stosl" \
17 ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
18
//// ��ָ����ַ��ʼ�ĵ�nr��λƫ�ƴ��ı���λ��λ��nr�ɴ���32����������ԭ����λֵ��
// ���룺%0 -eax������ֵ����%1 -eax(0)��%2 -nr��λƫ��ֵ��%3 -(addr)��addr�����ݡ�
// ��20�ж�����һ���ֲ��Ĵ�������res���ñ�������������ָ����eax�Ĵ����У��Ա���
// ��Ч���ʺͲ��������ֶ�������ķ�����Ҫ������Ƕ�������С���ϸ˵���μ�gcc�ֲ�
// ����ָ���Ĵ����еı������������궨����һ��������ʽ���ñ���ʽֵ�����res��ֵ��
// ��21���ϵ�btslָ�����ڲ��Բ����ñ���λ��Bit Test and Set�����ѻ���ַ��%3����
// ����λƫ��ֵ��%2����ָ���ı���λֵ�ȱ��浽��λ��־CF�У�Ȼ�����øñ���λΪ1��
// ָ��setb���ڸ��ݽ�λ��־CF���ò�������%al�������CF=1��%al =1������%al =0��
19 #define set_bit(nr,addr) ({\
20 register int res __asm__("ax"); \
21 __asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
22 "=a" (res):"" (0),"r" (nr),"m" (*(addr))); \
23 res;})
24
//// ��λָ����ַ��ʼ�ĵ�nrλƫ�ƴ��ı���λ������ԭ����λֵ�ķ��롣
// ���룺%0 -eax������ֵ����%1 -eax(0)��%2 -nr��λƫ��ֵ��%3 -(addr)��addr�����ݡ�
// ��27���ϵ�btrlָ�����ڲ��Բ���λ����λ��Bit Test and Reset�����������������
// btsl���ƣ����Ǹ�λָ������λ��ָ��setnb���ڸ��ݽ�λ��־CF���ò�������%al����
// ���CF = 1��%al = 0������%al = 1��
25 #define clear_bit(nr,addr) ({\
26 register int res __asm__("ax"); \
27 __asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
28 "=a" (res):"" (0),"r" (nr),"m" (*(addr))); \
29 res;})
30
//// ��addr��ʼѰ�ҵ�1��0ֵ����λ��
// ���룺%0 - ecx(����ֵ)��%1 - ecx(0)��%2 - esi(addr)��
// ��addrָ����ַ��ʼ��λͼ��Ѱ�ҵ�1����0�ı���λ�����������addr�ı���λƫ��
// ֵ���ء�addr�ǻ�����������ĵ�ַ��ɨ��Ѱ�ҵķ�Χ��1024�ֽڣ�8192����λ����
31 #define find_first_zero(addr) ({ \
32 int __res; \
33 __asm__("cld\n" \ // �巽��λ��
34 "1:\tlodsl\n\t" \ // ȡ[esi]��eax��
35 "notl %%eax\n\t" \ // eax��ÿλȡ����
36 "bsfl %%eax,%%edx\n\t" \ // ��λ0ɨ��eax����1�ĵ�1��λ����ƫ��ֵ��edx��
37 "je 2f\n\t" \ // ���eax��ȫ��0������ǰ��ת�����2��(40��)��
38 "addl %%edx,%%ecx\n\t" \ // ƫ��ֵ����ecx��ecx��λͼ��0ֵλ��ƫ��ֵ����
39 "jmp 3f\n" \ // ��ǰ��ת�����3������������
40 "2:\taddl $32,%%ecx\n\t" \ // δ�ҵ�0ֵλ����ecx��1�����ֵ�λƫ����32��
41 "cmpl $8192,%%ecx\n\t" \ // �Ѿ�ɨ����8192����λ��1024�ֽڣ�����
42 "jl 1b\n" \ // ����û��ɨ����1�����ݣ�����ǰ��ת�����1����
43 "3:" \ // ��������ʱecx����λƫ������
44 :"=c" (__res):"c" (0),"S" (addr):"ax","dx","si"); \
45 __res;})
46
//// �ͷ��豸dev���������е�����block��
// ��λָ������block��Ӧ������λͼ����λ���ɹ���1������0��
// ������dev���豸�ţ�block������ţ��̿�ţ���
47 int free_block(int dev, int block)
48 {
49 struct super_block * sb;
50 struct buffer_head * bh;
51
// ����ȡ�豸dev���ļ�ϵͳ�ij�������Ϣ������������������ʼ����ź��ļ�ϵͳ����
// ��������Ϣ�жϲ���block����Ч�ԡ����ָ���豸�����鲻���ڣ������ͣ����������
// ��С��������������1������Ŀ�Ż��ߴ����豸������������Ҳ����ͣ����
52 if (!(sb = get_super(dev))) // fs/super.c����56��
53 panic("trying to free block on nonexistent device");
54 if (block < sb->s_firstdatazone || block >= sb->s_nzones)
55 panic("trying to free block not in datazone");
56 bh = get_hash_table(dev,block);
// Ȼ��� hash����Ѱ�Ҹÿ����ݡ����ҵ������ж�����Ч�ԣ��������ĺ��±�־���ͷ�
// �����ݿ顣�öδ������Ҫ��;�����������Ŀǰ�����ڸ��ٻ������У����ͷŶ�Ӧ�Ļ�
// ��顣
57 if (bh) {
58 if (bh->b_count > 1) { // �����������1�������brelse()��
59 brelse(bh); // b_count--���˳����ÿ黹�����á�
60 return 0;
61 }
62 bh->b_dirt=0; // ����λ���ĺ��Ѹ��±�־��
63 bh->b_uptodate=0;
64 if (bh->b_count) // ����ʱb_countΪ1�������brelse()�ͷ�֮��
65 brelse(bh);
66 }
// �������Ǹ�λblock������λͼ�еı���λ����0�����ȼ���block����������ʼ�����
// ��������ţ���1��ʼ��������Ȼ�������(����)λͼ���в�������λ��Ӧ�ı���λ��
// �����Ӧ����λԭ������0�������ͣ��������1���������1024�ֽڣ���8192����λ��
// ��� block/8192 ���ɼ����ָ���� block ����λͼ�е��ĸ����ϡ��� block&8191 ��
// �Եõ�block������λͼ��ǰ���еı���ƫ��λ�á�
67 block -= sb->s_firstdatazone - 1 ; // ��block = block - ( s_firstdatazone -1);
68 if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) {
69 printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1);
70 printk("free_block: bit already cleared\n");
71 }
// �������Ӧ����λͼ���ڻ��������ı�־��
72 sb->s_zmap[block/8192]->b_dirt = 1;
73 return 1;
74 }
75
////���豸����һ�����飨�̿飬���飩��
// ��������ȡ���豸�ij����飬���ڳ������е�����λͼ��Ѱ�ҵ�һ��0ֵ����λ������
// һ���������飩��Ȼ����λ��Ӧ����������λͼ�еı���λ������Ϊ�������ڻ�
// ������ȡ��һ���Ӧ����顣��û�������㣬���������Ѹ��±�־�����ı�־��
// ����������š�����ִ�гɹ�������ţ��̿�ţ�������0��
76 int new_block(int dev)
77 {
78 struct buffer_head * bh;
79 struct super_block * sb;
80 int i,j;
81
// ���Ȼ�ȡ�豸dev�ij����顣���ָ���豸�ij����鲻���ڣ������ͣ����Ȼ��ɨ���ļ�
// ϵͳ��8������λͼ��Ѱ����0ֵ����λ����Ѱ�ҿ������飬��ȡ���ø������
// ��š� ���ȫ��ɨ����8������λͼ�����б���λ��i >= 8 �� j >= 8192����û�ҵ�
// 0ֵ����λ����λͼ���ڵĻ����ָ����Ч(bh = NULL)�� ����0�˳���û�п������飩��
82 if (!(sb = get_super(dev)))
83 panic("trying to get new block from nonexistant device");
84 j = 8192;
85 for (i=0 ; i<8 ; i++)
86 if (bh=sb->s_zmap[i])
87 if ((j=find_first_zero(bh->b_data))<8192)
88 break;
89 if (i>=8 || !bh || j>=8192)
90 return 0;
// ���������ҵ���������j��Ӧ����λͼ�еı���λ������Ӧ����λ�Ѿ���λ�������
// ͣ���������ô��λͼ�Ķ�Ӧ�����������ı�־����Ϊ����λͼ����ʾ������������
// �����ռ�������������λͼ�б���λƫ��ֵ��ʾ����������ʼ������Ŀ�ţ����
// ������Ҫ������������1������Ŀ�ţ���jת��������š���ʱ������������
// ���豸�ϵ�������������˵��ָ�������ڶ�Ӧ�豸�ϲ����ڡ�����ʧ�ܣ�����0�˳���
91 if (set_bit(j,bh->b_data))
92 panic("new_block: bit already set");
93 bh->b_dirt = 1;
94 j += i*8192 + sb->s_firstdatazone-1;
95 if (j >= sb->s_nzones)
96 return 0;
// Ȼ���ڸ��ٻ�������Ϊ���豸��ָ���������ȡ��һ������飬�����ػ����ͷָ�롣
// ��Ϊ��ȡ�õ����������ô���һ��Ϊ1��getblk()�л����ã����������Ϊ1��ͣ����
// ������������㣬���������Ѹ��±�־�����ı�־��Ȼ���ͷŶ�Ӧ����飬����
// ����š�
97 if (!(bh=getblk(dev,j)))
98 panic("new_block: cannot get block");
99 if (bh->b_count != 1)
100 panic("new block: count is != 1");
101 clear_block(bh->b_data);
102 bh->b_uptodate = 1;
103 bh->b_dirt = 1;
104 brelse(bh);
105 return j;
106 }
107
//// �ͷ�ָ����i�ڵ㡣
// �ú��������жϲ���������i�ڵ�ŵ���Ч�ԺͿ��ͷ��ԡ���i�ڵ���Ȼ��ʹ��������
// ���ͷš�Ȼ�����ó�������Ϣ��i�ڵ�λͼ���в�������λi�ڵ�Ŷ�Ӧ��i�ڵ�λͼ��
// ����λ�������i�ڵ�ṹ��
108 void free_inode(struct m_inode * inode)
109 {
110 struct super_block * sb;
111 struct buffer_head * bh;
112
// �����жϲ�����������Ҫ�ͷŵ�i�ڵ���Ч�Ի�Ϸ��ԡ����i�ڵ�ָ��=NULL�����˳���
// ���i�ڵ��ϵ��豸���ֶ�Ϊ0��˵���ýڵ�û��ʹ�á�������0��ն�Ӧi�ڵ���ռ�ڴ�
// �������ء�memset()������ include/string.h ��395�п�ʼ���������ʾ��0��дinode
// ָ��ָ������������ sizeof(*inode) ���ڴ�顣
113 if (!inode)
114 return;
115 if (!inode->i_dev) {
116 memset(inode,0,sizeof(*inode));
117 return;
118 }
// �����i�ڵ㻹�������������ã������ͷţ�˵���ں������⣬ͣ��������ļ�������
// ��Ϊ0�����ʾ���������ļ�Ŀ¼����ʹ�øýڵ㣬���Ҳ��Ӧ�ͷţ���Ӧ�÷Żصȡ�
119 if (inode->i_count>1) {
120 printk("trying to free inode with count=%d\n",inode->i_count);
121 panic("free_inode");
122 }
123 if (inode->i_nlinks)
124 panic("trying to free inode with links");
// ���ж���i�ڵ�ĺ�����֮�����ǿ�ʼ�����䳬������Ϣ�����е�i�ڵ�λͼ���в�����
// ����ȡi�ڵ������豸�ij����飬�����豸�Ƿ���ڡ�Ȼ���ж�i�ڵ�ŵķ�Χ�Ƿ���ȷ��
// ��� i�ڵ�ŵ���0 �� ���ڸ��豸�� i�ڵ��������������0��i�ڵ㱣��û��ʹ�ã���
// �����i�ڵ��Ӧ�Ľڵ�λͼ�����ڣ����������Ϊһ��������i�ڵ�λͼ�� 8192 ��
// ��λ�����i_num>>13����i_num/8192�����Եõ���ǰi�ڵ�����ڵ�s_imap[]�����
// ���̿顣
125 if (!(sb = get_super(inode->i_dev)))
126 panic("trying to free inode on nonexistent device");
127 if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
128 panic("trying to free inode 0 or nonexistant inode");
129 if (!(bh=sb->s_imap[inode->i_num>>13]))
130 panic("nonexistent imap in superblock");
// �������Ǹ�λi�ڵ��Ӧ�Ľڵ�λͼ�еı���λ������ñ���λ�Ѿ�����0������ʾ����
// ������Ϣ�������i�ڵ�λͼ���ڻ��������ı�־������ո�i�ڵ�ṹ��ռ�ڴ�����
131 if (clear_bit(inode->i_num&8191,bh->b_data))
132 printk("free_inode: bit already cleared.\n\r");
133 bh->b_dirt = 1;
134 memset(inode,0,sizeof(*inode));
135 }
136
//// Ϊ�豸dev����һ����i�ڵ㡣��ʼ�������ظ���i�ڵ��ָ�롣
// ���ڴ�i�ڵ���л�ȡһ������i�ڵ�������i�ڵ�λͼ����һ������i�ڵ㡣
137 struct m_inode * new_inode(int dev)
138 {
139 struct m_inode * inode;
140 struct super_block * sb;
141 struct buffer_head * bh;
142 int i,j;
143
// ���ȴ��ڴ�i�ڵ����inode_table���л�ȡһ������i�ڵ������ȡָ���豸�ij�����
// �ṹ�� Ȼ��ɨ�賬������8��i�ڵ�λͼ��Ѱ����0����λ��Ѱ�ҿ��нڵ㣬��ȡ����
// ��i�ڵ�Ľڵ�š����ȫ��ɨ���껹û�ҵ�������λͼ���ڵĻ������Ч��bh = NULL����
// ��Ż���ǰ�����i�ڵ���е�i�ڵ㣬�����ؿ�ָ���˳���û�п���i�ڵ㣩��
144 if (!(inode=get_empty_inode())) // fs/inode.c����197��
145 return NULL;
146 if (!(sb = get_super(dev))) // fs/super.c����56��
147 panic("new_inode with unknown device");
148 j = 8192;
149 for (i=0 ; i<8 ; i++)
150 if (bh=sb->s_imap[i])
151 if ((j=find_first_zero(bh->b_data))<8192)
152 break;
153 if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) {
154 iput(inode);
155 return NULL;
156 }
// ���������Ѿ��ҵ��˻�δʹ�õ�i�ڵ��j��������λi�ڵ�j��Ӧ��i�ڵ�λͼ��Ӧ��
// ��λ������Ѿ���λ�����������Ȼ����i�ڵ�λͼ���ڻ�������ı�־������ʼ��
// ��i�ڵ�ṹ��i_ctime��i�ڵ����ݸı�ʱ�䣩��
157 if (set_bit(j,bh->b_data))
158 panic("new_inode: bit already set");
159 bh->b_dirt = 1;
160 inode->i_count=1; // ���ü�����
161 inode->i_nlinks=1; // �ļ�Ŀ¼����������
162 inode->i_dev=dev; // i�ڵ����ڵ��豸�š�
163 inode->i_uid=current->euid; // i�ڵ������û�id��
164 inode->i_gid=current->egid; // ��id��
165 inode->i_dirt=1; // ���ı�־��λ��
166 inode->i_num = j + i*8192; // ��Ӧ�豸�е�i�ڵ�š�
167 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; // ����ʱ�䡣
168 return inode; // ���ظ�i�ڵ�ָ�롣
169 }
170
1 /*
2 * linux/fs/truncate.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
8
9 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
10
//// �ͷ�����һ�μ�ӿ顣���ڲ�������
// ����dev���ļ�ϵͳ�����豸���豸�ţ�block������š��ɹ���1������0��
11 static int free_ind(int dev,int block)
12 {
13 struct buffer_head * bh;
14 unsigned short * p;
15 int i;
16 int block_busy; // ������û�б��ͷŵı�־��
17
// �����жϲ�������Ч�ԡ���������Ϊ0���ء�Ȼ���ȡһ�μ�ӿ飬���ͷ����ϱ�
// ��ʹ�õ��������飬Ȼ���ͷŸ�һ�μ�ӿ�Ļ���顣 ����free_block()�����ͷ��豸
// ��ָ������ŵĴ��̿飨fs/bitmap.c��47�У���
18 if (!block)
19 return 1;
20 block_busy = 0;
21 if (bh=bread(dev,block)) {
22 p = (unsigned short *) bh->b_data; // ָ�����������
23 for (i=0;i<512;i++,p++) // ÿ�������Ͽ���512����š�
24 if (*p)
25 if (free_block(dev,*p)) { // �ͷ�ָ�����豸���顣
26 *p = 0; // ���㡣
27 bh->b_dirt = 1; // �������ı�־��
28 } else
29 block_busy = 1; // ��������û���ͷű�־��
30 brelse(bh); // Ȼ���ͷż�ӿ�ռ�õĻ���顣
31 }
// ����ͷ��豸�ϵ�һ�μ�ӿ顣���������������û�б��ͷţ���0��ʧ�ܣ���
32 if (block_busy)
33 return 0;
34 else
35 return free_block(dev,block); // �ɹ���1������0��
36 }
37
//// �ͷ����ж��μ�ӿ顣
// ����dev���ļ�ϵͳ�����豸���豸�ţ�block������š�
38 static int free_dind(int dev,int block)
39 {
40 struct buffer_head * bh;
41 unsigned short * p;
42 int i;
43 int block_busy; // ������û�б��ͷŵı�־��
44
// �����жϲ�������Ч�ԡ���������Ϊ0���ء�Ȼ���ȡ���μ�ӿ��һ���飬����
// �����ϱ���ʹ�õ��������飬Ȼ���ͷŸ�һ����Ļ���顣
45 if (!block)
46 return 1;
47 block_busy = 0;
48 if (bh=bread(dev,block)) {
49 p = (unsigned short *) bh->b_data; // ָ�����������
50 for (i=0;i<512;i++,p++) // ÿ�������Ͽ�����512�������顣
51 if (*p)
52 if (free_ind(dev,*p)) { // �ͷ�����һ�μ�ӿ顣
53 *p = 0; // ���㡣
54 bh->b_dirt = 1; // �������ı�־��
55 } else
56 block_busy = 1; // ��������û���ͷű�־��
57 brelse(bh); // �ͷŶ��μ�ӿ�ռ�õĻ���顣
58 }
// ����ͷ��豸�ϵĶ��μ�ӿ顣���������������û�б��ͷţ���0��ʧ�ܣ���
59 if (block_busy)
60 return 0;
61 else
62 return free_block(dev,block);
63 }
64
//// �ض��ļ����ݺ�����
// ���ڵ��Ӧ���ļ����Ƚ�Ϊ0�����ͷ�ռ�õ��豸�ռ䡣
65 void truncate(struct m_inode * inode)
66 {
67 int i;
68 int block_busy; // ������û�б��ͷŵı�־��
69
// �����ж�ָ��i�ڵ���Ч�ԡ�������dz����ļ���Ŀ¼�ļ���������ء�
70 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
71 S_ISLNK(inode->i_mode)))
72 return;
// Ȼ���ͷ�i�ڵ��7��ֱ�����飬������7��������ȫ���㡣����free_block()����
// �ͷ��豸��ָ������ŵĴ��̿飨fs/bitmap.c��47�У�����������æ��û�б��ͷ�
// ���ÿ�æ��־block_busy��
73 repeat:
74 block_busy = 0;
75 for (i=0;i<7;i++)
76 if (inode->i_zone[i]) { // �����Ų�Ϊ0�����ͷ�֮��
77 if (free_block(inode->i_dev,inode->i_zone[i]))
78 inode->i_zone[i]=0; // ��ָ����0��
79 else
80 block_busy = 1; // ��û���ͷŵ����ñ�־��
81 }
82 if (free_ind(inode->i_dev,inode->i_zone[7])) // �ͷ�����һ�μ�ӿ顣
83 inode->i_zone[7] = 0; // ��ָ����0��
84 else
85 block_busy = 1; // ��û���ͷŵ����ñ�־��
86 if (free_dind(inode->i_dev,inode->i_zone[8])) // �ͷ����ж��μ�ӿ顣
87 inode->i_zone[8] = 0; // ��ָ����0��
88 else
89 block_busy = 1; // ��û���ͷŵ����ñ�־��
// �˺�����i�ڵ����ı�־��������������������ڡ�æ����û�б��ͷţ���ѵ�ǰ����
// ����ʱ��Ƭ��0�����õ�ǰ�����ȱ��л�ȥ�����������̣��Ե�һ��������ִ���ͷŲ�����
90 inode->i_dirt = 1;
91 if (block_busy) {
92 current->counter = 0; // ��ǰ����ʱ��Ƭ��0��
93 schedule();
94 goto repeat;
95 }
96 inode->i_size = 0; // �ļ���С���㡣
// ����������ļ���ʱ���i�ڵ�ı�ʱ��Ϊ��ǰʱ�䡣�� CURRENT_TIME ������ͷ�ļ�
// include/linux/sched.h��142�д�������Ϊ(startup_time + jiffies/HZ)������ȡ�ô�
// 1970:0:0:0��ʼ������Ϊֹ������������
97 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
98 }
99
100
1 /*
2 * linux/fs/inode.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
9
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <linux/mm.h> // �ڴ����ͷ�ļ�������ҳ���С�����һЩҳ���ͷź���ԭ�͡�
13 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
14
// �豸���ݿ�����ָ�����顣ÿ��ָ����ָ��ָ�����豸�ŵ��ܿ�������hd_sizes[]������
// ��������ÿһ���Ӧ���豸��ȷ����һ�����豸����ӵ�е����ݿ�������1���С = 1KB����
15 extern int *blk_size[];
16
17 struct m_inode inode_table[NR_INODE]={{0,},}; // �ڴ���i�ڵ����NR_INODE=32���
18
19 static void read_inode(struct m_inode * inode); // ��ָ��i�ڵ�ŵ�i�ڵ���Ϣ��297�С�
20 static void write_inode(struct m_inode * inode); // дi�ڵ���Ϣ�����ٻ����У�324�С�
21
//// �ȴ�ָ����i�ڵ���á�
// ���i�ڵ��ѱ���������ǰ������Ϊ�����жϵĵȴ�״̬�������ӵ���i�ڵ�ĵȴ���
// ��i_wait�С�ֱ����i�ڵ��������ȷ�ػ��ѱ�����
22 static inline void wait_on_inode(struct m_inode * inode)
23 {
24 cli();
25 while (inode->i_lock)
26 sleep_on(&inode->i_wait); // kernel/sched.c����199��
27 sti();
28 }
29
//// ��i�ڵ�����������ָ����i�ڵ㣩��
// ���i�ڵ��ѱ���������ǰ������Ϊ�����жϵĵȴ�״̬�������ӵ���i�ڵ�ĵȴ���
// ��i_wait�С�ֱ����i�ڵ��������ȷ�ػ��ѱ�����Ȼ�����������
30 static inline void lock_inode(struct m_inode * inode)
31 {
32 cli();
33 while (inode->i_lock)
34 sleep_on(&inode->i_wait);
35 inode->i_lock=1; // ��������־��
36 sti();
37 }
38
//// ��ָ����i�ڵ������
// ��λi�ڵ��������־������ȷ�ػ��ѵȴ��ڴ�i�ڵ�ȴ�����i_wait�ϵ����н��̡�
39 static inline void unlock_inode(struct m_inode * inode)
40 {
41 inode->i_lock=0;
42 wake_up(&inode->i_wait); // kernel/sched.c����204��
43 }
44
//// �ͷ��豸dev���ڴ�i�ڵ���е�����i�ڵ㡣
// ɨ���ڴ��е�i�ڵ�����飬�����ָ���豸ʹ�õ�i�ڵ���ͷ�֮��
45 void invalidate_inodes(int dev)
46 {
47 int i;
48 struct m_inode * inode;
49
// ������ָ��ָ���ڴ�i�ڵ���������Ȼ��ɨ��i�ڵ��ָ�������е�����i�ڵ㡣���
// ����ÿ��i�ڵ㣬�ȵȴ���i�ڵ�������ã���Ŀǰ���������Ļ��������ж��Ƿ�����ָ��
// �豸��i�ڵ㡣�����ָ���豸��i�ڵ㣬�����Ƿ�ʹ���ţ��������ü����Ƿ�
// Ϊ0����������ʾ������Ϣ��Ȼ���ͷ�֮������i�ڵ���豸���ֶ�i_dev��0����50����
// ��ָ�븳ֵ "0+inode_table " ��ͬ�� "inode_table"��"&inode_table[0] "����������д
// ���ܸ�����һЩ��
50 inode = 0+inode_table; // ָ��i�ڵ��ָ���������
51 for(i=0 ; i<NR_INODE ; i++,inode++) {
52 wait_on_inode(inode); // �ȴ���i�ڵ���ã���������
53 if (inode->i_dev == dev) {
54 if (inode->i_count) // ������������Ϊ0������ʾ�������档
55 printk("inode in use on removed disk\n\r");
56 inode->i_dev = inode->i_dirt = 0; // �ͷ�i�ڵ�(���豸��Ϊ0)��
57 }
58 }
59 }
60
//// ͬ������i�ڵ㡣
// ���ڴ�i�ڵ��������i�ڵ����豸��i�ڵ���ͬ��������
61 void sync_inodes(void)
62 {
63 int i;
64 struct m_inode * inode;
65
// �������ڴ�i�ڵ����͵�ָ��ָ��i�ڵ�����Ȼ��ɨ������i�ڵ���еĽڵ㡣���
// ����ÿ��i�ڵ㣬�ȵȴ���i�ڵ�������ã���Ŀǰ���������Ļ�����Ȼ���жϸ�i�ڵ�
// �Ƿ��ѱ��IJ��Ҳ��ǹܵ��ڵ㡣�������������i�ڵ�д����ٻ������С�������
// ��������buffer.c�����ʵ�ʱ��������д�����С�
66 inode = 0+inode_table; // ��ָ������ָ��i�ڵ��ָ���������
67 for(i=0 ; i<NR_INODE ; i++,inode++) { // ɨ��i�ڵ��ָ�����顣
68 wait_on_inode(inode); // �ȴ���i�ڵ���ã���������
69 if (inode->i_dirt && !inode->i_pipe) // ��i�ڵ������Ҳ��ǹܵ��ڵ㣬
70 write_inode(inode); // ��д�̣�ʵ����д�뻺�����У���
71 }
72 }
73
//// �ļ����ݿ�ӳ�䵽�̿�Ĵ�����������blockλͼ����������bmap - block map��
// ������inode �C �ļ���i�ڵ�ָ�룻block �C �ļ��е����ݿ�ţ�create - �������־��
// �ú�����ָ�����ļ����ݿ�block��Ӧ���豸�������ϣ�����������š����������־
// ��λ�������豸�϶�Ӧ���鲻����ʱ�������´��̿飬�����ļ����ݿ�block��Ӧ���豸
// �ϵ�����ţ��̿�ţ���
74 static int _bmap(struct m_inode * inode,int block,int create)
75 {
76 struct buffer_head * bh;
77 int i;
78
// �����жϲ����ļ����ݿ��block����Ч�ԡ�������С��0����ͣ���������Ŵ���ֱ��
// ���� + ��ӿ��� + ���μ�ӿ����������ļ�ϵͳ��ʾ��Χ����ͣ����
79 if (block<0)
80 panic("_bmap: block<0");
81 if (block >= 7+512+512*512)
82 panic("_bmap: block>big");
// Ȼ������ļ���ŵĴ�Сֵ���Ƿ������˴�����־�ֱ���д���������ÿ��С��7����ʹ
// ��ֱ�ӿ��ʾ�����������־��λ������i�ڵ��ж�Ӧ�ÿ�����飨���Σ��ֶ�Ϊ0����
// ����Ӧ�豸����һ���̿飨���飩�����ҽ���������ţ��̿�ţ����������ֶ��С�
// Ȼ������i�ڵ�ı�ʱ�䣬��i�ڵ����ı�־�� �������š� ����new_block()
// ������bitmap.c�����е�76�п�ʼ����
83 if (block<7) {
84 if (create && !inode->i_zone[block])
85 if (inode->i_zone[block]=new_block(inode->i_dev)) {
86 inode->i_ctime=CURRENT_TIME; // ctime - Change time��
87 inode->i_dirt=1; // �������ı�־��
88 }
89 return inode->i_zone[block];
90 }
// ����ÿ��>=7����С��7+512����˵��ʹ�õ���һ�μ�ӿ顣�����һ�μ�ӿ���д�����
// ����Ǵ��������Ҹ�i�ڵ��ж�Ӧ��ӿ��ֶ�i_zone[7]��0�������ļ����״�ʹ�ü�ӿ飬
// ��������һ���̿����ڴ�ż�ӿ���Ϣ��������ʵ�ʴ��̿�������ӿ��ֶ��С� Ȼ����
// ��i�ڵ����ı�־����ʱ�䡣 �������ʱ������̿�ʧ�ܣ����ʱi�ڵ��ӿ��ֶ�
// i_zone[7]Ϊ0����0�����߲��Ǵ�������i_zone[7]ԭ����Ϊ0������i�ڵ���û�м�
// �ӿ飬����ӳ����̿�ʧ�ܣ�����0�˳���
91 block -= 7;
92 if (block<512) {
93 if (create && !inode->i_zone[7])
94 if (inode->i_zone[7]=new_block(inode->i_dev)) {
95 inode->i_dirt=1;
96 inode->i_ctime=CURRENT_TIME;
97 }
98 if (!inode->i_zone[7])
99 return 0;
// ���ڶ�ȡ�豸�ϸ�i�ڵ��һ�μ�ӿ顣��ȡ�ü�ӿ��ϵ�block���е�����ţ��̿�
// �ţ�i��ÿһ��ռ2���ֽڡ�����Ǵ������Ҽ�ӿ�ĵ�block���е������Ϊ0�Ļ���
// ������һ���̿飬���ü�ӿ��еĵ�block����ڸ��������š�Ȼ����λ��ӿ����
// �ı�־��������Ǵ�������i������Ҫӳ�䣨Ѱ�ң�������š�
100 if (!(bh = bread(inode->i_dev,inode->i_zone[7])))
101 return 0;
102 i = ((unsigned short *) (bh->b_data))[block];
103 if (create && !i)
104 if (i=new_block(inode->i_dev)) {
105 ((unsigned short *) (bh->b_data))[block]=i;
106 bh->b_dirt=1;
107 }
// ����ͷŸü�ӿ�ռ�õĻ���飬�����ش������������ԭ�еĶ�Ӧblock�������š�
108 brelse(bh);
109 return i;
110 }
// ���������е��ˣ���������ݿ����ڶ��μ�ӿ顣�䴦��������һ�μ�ӿ����ơ������Ƕ�
// ���μ�ӿ�Ĵ��������Ƚ�block�ټ�ȥ��ӿ������ɵĿ�����512����Ȼ������Ƿ�����
// �˴�����־���д�����Ѱ�Ҵ�����������´�������i�ڵ�Ķ��μ�ӿ��ֶ�Ϊ0��������
// ��һ���̿����ڴ�Ŷ��μ�ӿ��һ������Ϣ��������ʵ�ʴ��̿��������μ�ӿ��ֶ�
// �С�֮����i�ڵ����ı��ƺ���ʱ�䡣ͬ���أ��������ʱ������̿�ʧ�ܣ����
// ʱi�ڵ���μ�ӿ��ֶ�i_zone[8]Ϊ0����0�����߲��Ǵ�������i_zone[8]ԭ����
// Ϊ0������i�ڵ���û�м�ӿ飬����ӳ����̿�ʧ�ܣ�����0�˳���
111 block -= 512;
112 if (create && !inode->i_zone[8])
113 if (inode->i_zone[8]=new_block(inode->i_dev)) {
114 inode->i_dirt=1;
115 inode->i_ctime=CURRENT_TIME;
116 }
117 if (!inode->i_zone[8])
118 return 0;
// ���ڶ�ȡ�豸�ϸ�i�ڵ�Ķ��μ�ӿ顣��ȡ�ö��μ�ӿ��һ�����ϵ� (block/512)
// ���е������i������Ǵ������Ҷ��μ�ӿ��һ�����ϵ� (block/512) ���е���
// ���Ϊ0�Ļ�����������һ���̿飨���飩��Ϊ���μ�ӿ�Ķ�����i�����ö��μ��
// ���һ�����е� (block/512)����ڸö�����Ŀ��i��Ȼ����λ���μ�ӿ��һ������
// �ı�־�����ͷŶ��μ�ӿ��һ���顣������Ǵ�������i������Ҫӳ�䣨Ѱ�ң�����
// ����š�
119 if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
120 return 0;
121 i = ((unsigned short *)bh->b_data)[block>>9];
122 if (create && !i)
123 if (i=new_block(inode->i_dev)) {
124 ((unsigned short *) (bh->b_data))[block>>9]=i;
125 bh->b_dirt=1;
126 }
127 brelse(bh);
// ������μ�ӿ�Ķ�������Ϊ0����ʾ������̿�ʧ�ܻ���ԭ����Ӧ��ž�Ϊ0����
// ��0�˳�������ʹ��豸�϶�ȡ���μ�ӿ�Ķ����飬��ȡ�ö������ϵ�block���е���
// ����ţ�����511��Ϊ����blockֵ������511����
128 if (!i)
129 return 0;
130 if (!(bh=bread(inode->i_dev,i)))
131 return 0;
132 i = ((unsigned short *)bh->b_data)[block&511];
// ����Ǵ������Ҷ�����ĵ�block���������Ϊ0�Ļ���������һ���̿飨���飩��
// ��Ϊ���մ��������Ϣ�Ŀ顣���ö������еĵ�block����ڸ���������(i)��Ȼ��
// ��λ����������ı�־��
133 if (create && !i)
134 if (i=new_block(inode->i_dev)) {
135 ((unsigned short *) (bh->b_data))[block&511]=i;
136 bh->b_dirt=1;
137 }
// ����ͷŸö��μ�ӿ�Ķ����飬���ش�����������Ļ�ԭ�еĶ�Ӧblock�������š�
138 brelse(bh);
139 return i;
140 }
141
//// ȡ�ļ����ݿ�block���豸�϶�Ӧ������š�
// ������inode �C �ļ����ڴ�i�ڵ�ָ�룻block �C �ļ��е����ݿ�š�
// �������ɹ��ض�Ӧ������ţ�����0��
142 int bmap(struct m_inode * inode,int block)
143 {
144 return _bmap(inode,block,0);
145 }
146
//// ȡ�ļ����ݿ�block���豸�϶�Ӧ������š������Ӧ�����鲻���ھʹ���һ�顣
// �������豸�϶�Ӧ������š�
// ������inode �C �ļ����ڴ�i�ڵ�ָ�룻block �C �ļ��е����ݿ�š�
// �������ɹ��ض�Ӧ������ţ�����0��
147 int create_block(struct m_inode * inode, int block)
148 {
149 return _bmap(inode,block,1);
150 }
151
//// �Żأ����ã�һ��i�ڵ�(��д���豸)��
// �ú�����Ҫ���ڰ�i�ڵ����ü���ֵ�ݼ�1���������ǹܵ�i�ڵ㣬���ѵȴ��Ľ��̡�
// ���ǿ��豸�ļ�i�ڵ���ˢ���豸��������i�ڵ�����Ӽ���Ϊ0�����ͷŸ�i�ڵ�ռ��
// �����д������飬���ͷŸ�i�ڵ㡣
152 void iput(struct m_inode * inode)
153 {
// �����жϲ���������i�ڵ����Ч�ԣ����ȴ�inode�ڵ����������������Ļ��������i
// �ڵ�����ü���Ϊ0����ʾ��i�ڵ��Ѿ��ǿ��еġ��ں���Ҫ�������зŻز�����˵����
// �����������������⡣������ʾ������Ϣ��ͣ����
154 if (!inode)
155 return;
156 wait_on_inode(inode);
157 if (!inode->i_count)
158 panic("iput: trying to free free inode");
// ����ǹܵ�i�ڵ㣬���ѵȴ��ùܵ��Ľ��̣����ô�����1��������������ء�����
// �ͷŹܵ�ռ�õ��ڴ�ҳ�棬����λ�ýڵ�����ü���ֵ�����ı�־�ܵ���־�������ء�
// ���ڹܵ��ڵ㣬inode->i_size������ڴ�ҳ��ַ���μ�get_pipe_inode()��231��237�С�
159 if (inode->i_pipe) {
160 wake_up(&inode->i_wait);
161 wake_up(&inode->i_wait2); //
162 if (--inode->i_count)
163 return;
164 free_page(inode->i_size);
165 inode->i_count=0;
166 inode->i_dirt=0;
167 inode->i_pipe=0;
168 return;
169 }
// ���i�ڵ��Ӧ���豸�� = 0���˽ڵ�����ü����ݼ�1�����ء��������ڹܵ�������
// i�ڵ㣬��i�ڵ���豸��Ϊ0��
170 if (!inode->i_dev) {
171 inode->i_count--;
172 return;
173 }
// ����ǿ��豸�ļ���i�ڵ㣬��ʱ�����ֶ�0��i_zone[0]�������豸�ţ���ˢ�¸��豸��
// ���ȴ�i�ڵ������
174 if (S_ISBLK(inode->i_mode)) {
175 sync_dev(inode->i_zone[0]);
176 wait_on_inode(inode);
177 }
// ���i�ڵ�����ü�������1��������ݼ�1���ֱ�ӷ��أ���Ϊ��i�ڵ㻹�������ã�����
// �ͷţ��������˵��i�ڵ�����ü���ֵΪ1����Ϊ��157���Ѿ��жϹ����ü����Ƿ�Ϊ�㣩��
// ���i�ڵ��������Ϊ0����˵��i�ڵ��Ӧ�ļ���ɾ���������ͷŸ�i�ڵ���������飬
// ���ͷŸ�i�ڵ㡣����free_inode()����ʵ���ͷ�i�ڵ����������λi�ڵ��Ӧ��i�ڵ�λ
// ͼ����λ�����i�ڵ�ṹ���ݡ�
178 repeat:
179 if (inode->i_count>1) {
180 inode->i_count--;
181 return;
182 }
183 if (!inode->i_nlinks) {
184 truncate(inode);
185 free_inode(inode); // bitmap.c ��108�п�ʼ����
186 return;
187 }
// �����i�ڵ��������ģ����д���¸�i�ڵ㣬���ȴ���i�ڵ����������������дi��
// ��ʱ��Ҫ�ȴ�˯�ߣ���ʱ���������п����ĸ�i�ڵ㣬����ڽ��̱����Ѻ���Ҫ�ٴ��ظ�
// ���������жϹ��̣�repeat����
188 if (inode->i_dirt) {
189 write_inode(inode); /* we can sleep - so do again */
190 wait_on_inode(inode); /* ��Ϊ����˯���ˣ�������Ҫ�ظ��ж� */
191 goto repeat;
192 }
// ��������ִ�е��ˣ���˵����i�ڵ�����ü���ֵi_count��1����������Ϊ�㣬��������
// û�б��Ĺ�����˴�ʱֻҪ��i�ڵ����ü����ݼ�1�����ء���ʱ��i�ڵ��i_count=0��
// ��ʾ���ͷš�
193 inode->i_count--;
194 return;
195 }
196
//// ��i�ڵ����inode_table���л�ȡһ������i�ڵ��
// Ѱ�����ü���countΪ0��i�ڵ㣬������д�̺����㣬������ָ�롣���ü�������1��
197 struct m_inode * get_empty_inode(void)
198 {
199 struct m_inode * inode;
200 static struct m_inode * last_inode = inode_table; // ָ��i�ڵ����1�
201 int i;
202
// �ڳ�ʼ��last_inodeָ��ָ��i�ڵ��ͷһ���ѭ��ɨ������i�ڵ�������last_inode
// �Ѿ�ָ��i�ڵ�������1��֮������������ָ��i�ڵ����ʼ�����Լ���ѭ��Ѱ�ҿ���
// i�ڵ����� last_inode��ָ���i�ڵ�ļ���ֵΪ0����˵�������ҵ�����i�ڵ��
// ��inodeָ���i�ڵ㡣�����i�ڵ�����ı�־��������־��Ϊ0�������ǿ���ʹ�ø�
// i�ڵ㣬�����˳�forѭ����
203 do {
204 inode = NULL;
205 for (i = NR_INODE; i ; i--) { // NR_INODE = 32��
206 if (++last_inode >= inode_table + NR_INODE)
207 last_inode = inode_table;
208 if (!last_inode->i_count) {
209 inode = last_inode;
210 if (!inode->i_dirt && !inode->i_lock)
211 break;
212 }
213 }
// ���û���ҵ�����i�ڵ㣨inode = NULL������i�ڵ����ӡ����������ʹ�ã���ͣ����
214 if (!inode) {
215 for (i=0 ; i<NR_INODE ; i++)
216 printk("%04x: %6d\t",inode_table[i].i_dev,
217 inode_table[i].i_num);
218 panic("No free inodes in mem");
219 }
// �ȴ���i�ڵ����������ֱ������Ļ����������i�ڵ����ı�־����λ�Ļ�����
// i�ڵ�ˢ�£�ͬ��������Ϊˢ��ʱ���ܻ�˯�ߣ������Ҫ�ٴ�ѭ���ȴ���i�ڵ������
220 wait_on_inode(inode);
221 while (inode->i_dirt) {
222 write_inode(inode);
223 wait_on_inode(inode);
224 }
225 } while (inode->i_count);
// ���i�ڵ��ֱ�����ռ�õĻ���i�ڵ�ļ���ֵ��Ϊ0�ˣ���������Ѱ�ҿ���i�ڵ㡣����
// ˵�����ҵ�����Ҫ��Ŀ���i�ڵ����i�ڵ����������㣬�������ü���Ϊ1������
// ��i�ڵ�ָ�롣
226 memset(inode,0,sizeof(*inode));
227 inode->i_count = 1;
228 return inode;
229 }
230
//// ��ȡ�ܵ��ڵ㡣
// ����ɨ��i�ڵ����Ѱ��һ������i�ڵ��Ȼ��ȡ��һҳ�����ڴ湩�ܵ�ʹ�á�Ȼ��
// ����i�ڵ�����ü�����Ϊ2(���ߺ�д��)����ʼ���ܵ�ͷ��β����i�ڵ�Ĺܵ����ͱ�ʾ��
// ����Ϊi�ڵ�ָ�룬���ʧ����NULL��
231 struct m_inode * get_pipe_inode(void)
232 {
233 struct m_inode * inode;
234
// ���ȴ��ڴ�i�ڵ����ȡ��һ������i�ڵ㡣����Ҳ�������i�ڵ���NULL��Ȼ��Ϊ��
// i�ڵ�����һҳ�ڴ棬���ýڵ��i_size�ֶ�ָ���ҳ�档�����û�п����ڴ棬���ͷŸ�
// i�ڵ㣬������NULL��
235 if (!(inode = get_empty_inode()))
236 return NULL;
237 if (!(inode->i_size=get_free_page())) { // �ڵ��i_size�ֶ�ָ������
238 inode->i_count = 0;
239 return NULL;
240 }
// Ȼ�����ø�i�ڵ�����ü���Ϊ2������λ��λ�ܵ�ͷβָ�롣i�ڵ����������i_zone[]
// ��i_zone[0]��i_zone[1]�зֱ�������Źܵ�ͷ�ܵ�βָ�롣�������i�ڵ��ǹܵ�i��
// ���־�����ظ�i�ڵ�š�
241 inode->i_count = 2; /* sum of readers/writers */ /* ��/д�����ܼ� */
242 PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; // ��λ�ܵ�ͷβָ�롣
243 inode->i_pipe = 1; // �ýڵ�Ϊ�ܵ�ʹ�õı�־��
244 return inode;
245 }
246
//// ȡ��һ��i�ڵ㡣
// ������dev - �豸�ţ�nr - i�ڵ�š�
// ���豸�϶�ȡָ���ڵ�ŵ�i�ڵ�ṹ���ݵ��ڴ�i�ڵ���У����ҷ��ظ�i�ڵ�ָ�롣
// ������λ�ڸ��ٻ������е�i�ڵ������Ѱ�����ҵ�ָ���ڵ�ŵ�i�ڵ����ھ���һЩ�ж�
// �����ظ�i�ڵ�ָ�롣������豸dev�϶�ȡָ��i�ڵ�ŵ�i�ڵ���Ϣ����i�ڵ��
// �У������ظ�i�ڵ�ָ�롣
247 struct m_inode * iget(int dev,int nr)
248 {
249 struct m_inode * inode, * empty;
250
// �����жϲ�����Ч�ԡ����豸����0��������ں˴������⣬��ʾ������Ϣ��ͣ����Ȼ��Ԥ
// �ȴ�i�ڵ����ȡһ������i�ڵ㱸�á�
251 if (!dev)
252 panic("iget with dev==0");
253 empty = get_empty_inode();
// ����ɨ��i�ڵ����Ѱ�Ҳ���ָ���ڵ��nr��i�ڵ㡣�������ýڵ�����ô����������
// ǰɨ��i�ڵ���豸�Ų�����ָ�����豸�Ż��߽ڵ�Ų�����ָ���Ľڵ�ţ������ɨ�衣
254 inode = inode_table;
255 while (inode < NR_INODE+inode_table) {
256 if (inode->i_dev != dev || inode->i_num != nr) {
257 inode++;
258 continue;
259 }
// ����ҵ�ָ���豸��dev �ͽڵ�� nr ��i�ڵ㣬��ȴ��ýڵ����������������Ļ�����
// �ڵȴ��ýڵ���������У�i�ڵ�����ܻᷢ���仯�������ٴν���������ͬ�жϡ������
// ���˱仯�����ٴ�����ɨ������i�ڵ����
260 wait_on_inode(inode);
261 if (inode->i_dev != dev || inode->i_num != nr) {
262 inode = inode_table;
263 continue;
264 }
// �������ʾ�ҵ���Ӧ��i�ڵ㡣���ǽ���i�ڵ����ü�����1��Ȼ��������һ����飬����
// �Ƿ�����һ���ļ�ϵͳ�İ�װ�㡣������Ѱ�ұ���װ�ļ�ϵͳ���ڵ㲢���ء������i�ڵ�
// ��ȷ�������ļ�ϵͳ�İ�װ�㣬���ڳ����������Ѱ��װ�ڴ�i�ڵ�ij����顣���û����
// ��������ʾ������Ϣ�����Żر�������ʼʱ��ȡ�Ŀ��нڵ�empty�����ظ�i�ڵ�ָ�롣
265 inode->i_count++;
266 if (inode->i_mount) {
267 int i;
268
269 for (i = 0 ; i<NR_SUPER ; i++)
270 if (super_block[i].s_imount==inode)
271 break;
272 if (i >= NR_SUPER) {
273 printk("Mounted inode hasn't got sb\n");
274 if (empty)
275 iput(empty);
276 return inode;
277 }
// ִ�е������ʾ�Ѿ��ҵ���װ��inode�ڵ���ļ�ϵͳ�����顣���ǽ���i�ڵ�д�̷Żأ�
// ���Ӱ�װ�ڴ�i�ڵ��ϵ��ļ�ϵͳ��������ȡ�豸�ţ�����i�ڵ��ΪROOT_INO����Ϊ1��
// Ȼ������ɨ������i�ڵ�����Ի�ȡ�ñ���װ�ļ�ϵͳ�ĸ�i�ڵ���Ϣ��
278 iput(inode);
279 dev = super_block[i].s_dev;
280 nr = ROOT_INO;
281 inode = inode_table;
282 continue;
283 }
// ���������ҵ�����Ӧ��i�ڵ㡣��˿��Է�����������ʼ����ʱ����Ŀ���i�ڵ㣬����
// �ҵ���i�ڵ�ָ�롣
284 if (empty)
285 iput(empty);
286 return inode;
287 }
// ���������i�ڵ����û���ҵ�ָ����i�ڵ㣬������ǰ������Ŀ���i�ڵ�empty��i
// �ڵ���н�����i�ڵ㡣������Ӧ�豸�϶�ȡ��i�ڵ���Ϣ�����ظ�i�ڵ�ָ�롣
288 if (!empty)
289 return (NULL);
290 inode=empty;
291 inode->i_dev = dev; // ����i�ڵ���豸��
292 inode->i_num = nr; // ����i�ڵ�š�
293 read_inode(inode);
294 return inode;
295 }
296
//// ��ȡָ��i�ڵ���Ϣ��
// ���豸�϶�ȡ����ָ��i�ڵ���Ϣ��i�ڵ��̿飬Ȼ���Ƶ�ָ����i�ڵ�ṹ�С� Ϊ��
// ȷ��i�ڵ����ڵ��豸����ţ���飩���������ȶ�ȡ��Ӧ�豸�ϵij����飬�Ի�ȡ
// ���ڼ�������ŵ�ÿ��i�ڵ�����Ϣ INODES_PER_BLOCK�� �ڼ����i�ڵ����ڵ�����
// �źͰѸ��������һ������С�Ȼ��ѻ��������Ӧλ�ô���i�ڵ����ݸ��Ƶ�����
// ָ����λ�ô���
297 static void read_inode(struct m_inode * inode)
298 {
299 struct super_block * sb;
300 struct buffer_head * bh;
301 int block;
302
// ����������i�ڵ㣬��ȡ�ýڵ������豸�ij����顣
303 lock_inode(inode);
304 if (!(sb=get_super(inode->i_dev)))
305 panic("trying to read inode without dev");
// ��i�ڵ����ڵ��豸����� = (������ + ������) + i�ڵ�λͼռ�õĿ��� + ����λ
// ͼռ�õĿ��� + (i�ڵ��-1)/ÿ�麬�е�i�ڵ�������Ȼi�ڵ�Ŵ�0��ʼ��ţ�����1
// ��0��i�ڵ㲻�ã����Ҵ�����Ҳ�������Ӧ��0��i�ڵ�ṹ����˴��i�ڵ���̿��
// ��1���ϱ������i�ڵ������1--16��i�ڵ�ṹ������0--15�ġ�������������i��
// ��Ŷ�Ӧ��i�ڵ�ṹ�����̿�ʱ��Ҫ��1������B =(i�ڵ��-1)/ÿ�麬��i�ڵ�ṹ����
// ���磬�ڵ��16��i�ڵ�ṹӦ����B=(16-1)/16 = 0�Ŀ��ϡ� �������Ǵ��豸�϶�ȡ��
// i�ڵ����ڵ����飬������ָ��i�ڵ����ݵ�inodeָ����ָλ�ô���
306 block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
307 (inode->i_num-1)/INODES_PER_BLOCK;
308 if (!(bh=bread(inode->i_dev,block)))
309 panic("unable to read i-node block");
310 *(struct d_inode *)inode =
311 ((struct d_inode *)bh->b_data)
312 [(inode->i_num-1)%INODES_PER_BLOCK];
// ����ͷŶ���Ļ���飬��������i�ڵ㡣���ڿ��豸�ļ�������Ҫ����i�ڵ���ļ����
// ����ֵ��
313 brelse(bh);
314 if (S_ISBLK(inode->i_mode)) {
315 int i = inode->i_zone[0]; // ���ڿ��豸�ļ���i_zone[0]�����豸�š�
316 if (blk_size[MAJOR(i)])
317 inode->i_size = 1024*blk_size[MAJOR(i)][MINOR(i)];
318 else
319 inode->i_size = 0x7fffffff;
320 }
321 unlock_inode(inode);
322 }
323
//// ��i�ڵ���Ϣд�뻺�����С�
// �ú����Ѳ���ָ����i�ڵ�д�뻺������Ӧ�Ļ�����У���������ˢ��ʱ��д�����С�Ϊ��
// ȷ��i�ڵ����ڵ��豸����ţ���飩���������ȶ�ȡ��Ӧ�豸�ϵij����飬�Ի�ȡ
// ���ڼ�������ŵ�ÿ��i�ڵ�����Ϣ INODES_PER_BLOCK�� �ڼ����i�ڵ����ڵ�����
// �źͰѸ��������һ������С�Ȼ���i�ڵ����ݸ��Ƶ���������Ӧλ�ô���
324 static void write_inode(struct m_inode * inode)
325 {
326 struct super_block * sb;
327 struct buffer_head * bh;
328 int block;
329
// ����������i�ڵ㣬�����i�ڵ�û�б��Ĺ����߸�i�ڵ���豸�ŵ����㣬�������
// i�ڵ㣬���˳�������û�б��Ĺ���i�ڵ㣬�������뻺�����л��豸�е���ͬ�� Ȼ��
// ��ȡ��i�ڵ�ij����顣
330 lock_inode(inode);
331 if (!inode->i_dirt || !inode->i_dev) {
332 unlock_inode(inode);
333 return;
334 }
335 if (!(sb=get_super(inode->i_dev)))
336 panic("trying to write inode without device");
// ��i�ڵ����ڵ��豸����� = (������ + ������) + i�ڵ�λͼռ�õĿ��� + ����λ
// ͼռ�õĿ��� + (i�ڵ��-1)/ÿ�麬�е�i�ڵ����� ���Ǵ��豸�϶�ȡ��i�ڵ����ڵ�
// ���飬������i�ڵ���Ϣ���Ƶ������Ӧ��i�ڵ����λ�ô���
337 block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
338 (inode->i_num-1)/INODES_PER_BLOCK;
339 if (!(bh=bread(inode->i_dev,block)))
340 panic("unable to read i-node block");
341 ((struct d_inode *)bh->b_data)
342 [(inode->i_num-1)%INODES_PER_BLOCK] =
343 *(struct d_inode *)inode;
// Ȼ���û��������ı�־����i�ڵ������Ѿ��뻺�����е�һ�£�����ı�־���㡣Ȼ��
// �ͷŸú���i�ڵ�Ļ���������������i�ڵ㡣
344 bh->b_dirt=1;
345 inode->i_dirt=0;
346 brelse(bh);
347 unlock_inode(inode);
348 }
349
1 /*
2 * linux/fs/super.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * super.c contains code to handle the super-block tables.
9 */
/*
* super.c�����к��д�����������Ĵ��롣
*/
10 #include <linux/config.h> // �ں�����ͷ�ļ�������������Ժ�Ӳ�����ͣ�HD_TYPE����ѡ�
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
13 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
14
15 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
16 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
17
// ��ָ���豸ִ�и��ٻ������豸�����ݵ�ͬ��������fs/buffer.c��59�У���
18 int sync_dev(int dev);
// �ȴ�������kernel/chr_drv/tty_io.c��140�У���
19 void wait_for_keypress(void);
20
21 /* set_bit uses setb, as gas doesn't recognize setc */
/* set_bit()ʹ����setbָ���Ϊ��������gas����ʶ��ָ��setc */
//// ����ָ��λƫ�ƴ�����λ��ֵ�������ظ�ԭ����λֵ��Ӧ��ȡ��Ϊtest_bit()����������
// Ƕ��ʽ���ꡣ����bitnr�DZ���λƫ��ֵ��addr�Dz��Ա���λ��������ʼ��ַ��
// %0 - ax(__res)��%1 - 0��%2 - bitnr��%3 - addr
// ��23�ж�����һ���ֲ��Ĵ����������ñ�������������eax�Ĵ����У��Ա��ڸ�Ч���ʺ�
// ��������24����ָ��bt ���ڶԱ���λ���в��ԣ�Bit Test��������ѵ�ַaddr��%3����
// ����λƫ����bitnr��%2��ָ���ı���λ��ֵ�����λ��־CF �С� ָ��setb���ڸ��ݽ�
// λ��־CF���ò�����%al�����CF = 1��%al = 1������%al = 0��
22 #define set_bit(bitnr,addr) ({ \
23 register int __res __asm__("ax"); \
24 __asm__("bt %2,%3;setb %%al":"=a" (__res):"a" (0),"r" (bitnr),"m" (*(addr))); \
25 __res; })
26
27 struct super_block super_block[NR_SUPER]; // ������ṹ�����飨NR_SUPER = 8����
28 /* this is initialized in init/main.c */
/* ROOT_DEV����init/main.c�б���ʼ�� */
29 int ROOT_DEV = 0; // ���ļ�ϵͳ�豸�š�
30
// ����3��������lock_super()��free_super()��wait_on_super()����������inode.c��
// ����ͷ3��������������ͬ��ֻ����������Ķ����˳����顣
//// ���������顣
// ����������ѱ���������ǰ������Ϊ�����жϵĵȴ�״̬�������ӵ��ó�����ȴ���
// ��s_wait�С�ֱ���ó������������ȷ�ػ��ѱ�����Ȼ�����������
31 static void lock_super(struct super_block * sb)
32 {
33 cli(); // ���жϡ�
34 while (sb->s_lock) // ����ó������Ѿ���������˯�ߵȴ���
35 sleep_on(&(sb->s_wait)); // kernel/sched.c����199��
36 sb->s_lock = 1; // ���ó������������������־����
37 sti(); // ���жϡ�
38 }
39
//// ��ָ�������������
// ��λ�������������־������ȷ�ػ��ѵȴ��ڴ˳�����ȴ�����s_wait�ϵ����н��̡�
// ���ʹ��ulock_super�����������ܸ�������
40 static void free_super(struct super_block * sb)
41 {
42 cli();
43 sb->s_lock = 0; // ��λ������־��
44 wake_up(&(sb->s_wait)); // ���ѵȴ��ó�����Ľ��̡�
45 sti(); // wake_up()��kernel/sched.c����188��
46 }
47
//// ˯�ߵȴ������������
// ����������ѱ���������ǰ������Ϊ�����жϵĵȴ�״̬�������ӵ��ó�����ĵȴ���
// ��s_wait�С�ֱ���ó������������ȷ�ػ��ѱ�����
48 static void wait_on_super(struct super_block * sb)
49 {
50 cli();
51 while (sb->s_lock) // ����������Ѿ���������˯�ߵȴ���
52 sleep_on(&(sb->s_wait));
53 sti();
54 }
55
//// ȡָ���豸�ij����顣
// �ڳ�����������飩������ָ���豸dev�ij�����ṹ��Ϣ�����ҵ��س������ָ�룬
// ���ؿ�ָ�롣
56 struct super_block * get_super(int dev)
57 {
58 struct super_block * s; // s�dz��������ݽṹָ�롣
59
// �����жϲ��������豸����Ч�ԡ����豸��Ϊ0�ؿ�ָ�롣Ȼ����sָ��������
// ��ʼ������ʼ�����������������飬��Ѱ��ָ���豸dev�ij����顣 ��62���ϵ�ָ�븳
// ֵ���"s = 0+super_block" ��ͬ�� "s = super_block"��"s = &super_block[0]"��
60 if (!dev)
61 return NULL;
62 s = 0+super_block;
63 while (s < NR_SUPER+super_block)
// �����ǰ��������ָ���豸�ij����飬���ó�������豸���ֶ�ֵ�뺯������ָ������ͬ��
// ���ȵȴ��ó�������������ѱ��������������Ļ������ڵȴ��ڼ䣬�ó��������п��ܱ�
// �����豸ʹ�ã���˵ȴ�����֮�������ж�һ���Ƿ���ָ���豸�ij����飬�������
// �ó������ָ�롣��������¶Գ���������������һ�飬��˴�ʱs������ָ������
// �鿪ʼ����
64 if (s->s_dev == dev) {
65 wait_on_super(s);
66 if (s->s_dev == dev)
67 return s;
68 s = 0+super_block;
// �����ǰ������ǣ�������һ����û���ҵ�ָ���ij����飬�ؿ�ָ�롣
69 } else
70 s++;
71 return NULL;
72 }
73
//// �ͷţ��Żأ�ָ���豸�ij����顣
// �ͷ��豸��ʹ�õij������������s_dev=0�������ͷŸ��豸i�ڵ�λͼ������λͼ��
// ռ�õĸ��ٻ���顣����������Ӧ���ļ�ϵͳ�Ǹ��ļ�ϵͳ��������ij��i�ڵ����Ѿ���
// װ���������ļ�ϵͳ�������ͷŸó����顣
74 void put_super(int dev)
75 {
76 struct super_block * sb;
77 int i;
78
// �����жϲ�������Ч�ԺͺϷ��ԡ����ָ���豸�Ǹ��ļ�ϵͳ�豸������ʾ������Ϣ����ϵ
// ͳ�̸ı��ˣ���������ս�ɡ��������ء�Ȼ���ڳ��������Ѱ��ָ���豸�ŵ��ļ�ϵͳ��
// ���顣����Ҳ���ָ���豸�ij����飬�ء����⣬����ó�����ָ�����ļ�ϵͳ����װ
// ����i�ڵ㻹û�б�������������ʾ������Ϣ�����ء����ļ�ϵͳж�أ�umount�������У�
// s_imount���ȱ��ó�Null�Ժ�Ż���ñ��������μ���192�С�
79 if (dev == ROOT_DEV) {
80 printk("root diskette changed: prepare for armageddon\n\r");
81 return;
82 }
83 if (!(sb = get_super(dev)))
84 return;
85 if (sb->s_imount) {
86 printk("Mounted disk changed - tssk, tssk\n\r");
87 return;
88 }
// Ȼ�����ҵ�ָ���豸�ij�����֮�������������ó����飬���øó������Ӧ���豸���ֶ�
// s_dev Ϊ0��Ҳ���ͷŸ��豸�ϵ��ļ�ϵͳ�����顣Ȼ���ͷŸó�����ռ�õ������ں���Դ��
// ���ͷŸ��豸���ļ�ϵͳi�ڵ�λͼ������λͼ�ڻ���������ռ�õĻ���顣���泣����
// ��I_MAP_SLOTS��Z_MAP_SLOTS������8�����ڷֱ�ָ��i�ڵ�λͼ������λͼռ�õĴ�
// ����������ע�⣬����Щ��������ݱ��Ĺ�������Ҫ��ͬ���������ܰѻ�����е�����
// д���豸�С��������Ըó���������������ء�
89 lock_super(sb);
90 sb->s_dev = 0; // �ó�������С�
91 for(i=0;i<I_MAP_SLOTS;i++)
92 brelse(sb->s_imap[i]);
93 for(i=0;i<Z_MAP_SLOTS;i++)
94 brelse(sb->s_zmap[i]);
95 free_super(sb);
96 return;
97 }
98
//// ��ȡָ���豸�ij����顣
// ���ָ���豸dev�ϵ��ļ�ϵͳ�������Ѿ��ڳ�������У���ֱ�ӷ��ظó��������ָ�롣
// ����ʹ��豸dev�϶�ȡ�����鵽������У������Ƶ���������С������س�����ָ�롣
99 static struct super_block * read_super(int dev)
100 {
101 struct super_block * s;
102 struct buffer_head * bh;
103 int i,block;
104
// �����жϲ�������Ч�ԡ����û��ָ���豸���ؿ�ָ�롣Ȼ������豸�Ƿ�ɸ���
// ����Ƭ��Ҳ���Ƿ��������豸��������������̣�����ٻ������йظ��豸�����л����
// ��ʧЧ����Ҫ����ʧЧ���������ͷ�ԭ�����ص��ļ�ϵͳ��
105 if (!dev)
106 return NULL;
107 check_disk_change(dev);
// ������豸�ij������Ѿ��ڳ�������У���ֱ�ӷ��ظó������ָ�롣���������ڳ���
// ���������ҳ�һ������(Ҳ���ֶ�s_dev=0����)����������Ѿ�ռ���ؿ�ָ�롣
108 if (s = get_super(dev))
109 return s;
110 for (s = 0+super_block ;; s++) {
111 if (s >= NR_SUPER+super_block)
112 return NULL;
113 if (!s->s_dev)
114 break;
115 }
// �ڳ������������ҵ�����֮�ͽ��ó�����������ָ���豸dev�ϵ��ļ�ϵͳ�����Ƕ�
// �ó�����ṹ�е��ڴ��ֶν��в��ֳ�ʼ��������
116 s->s_dev = dev; // ����dev�豸�ϵ��ļ�ϵͳ��
117 s->s_isup = NULL;
118 s->s_imount = NULL;
119 s->s_time = 0;
120 s->s_rd_only = 0;
121 s->s_dirt = 0;
// Ȼ�������ó����飬�����豸�϶�ȡ��������Ϣ��bhָ��Ļ�����С�������λ�ڿ��豸
// �ĵ�2�����飨1�ſ飩�У�����1���������̿飩����������������ʧ�ܣ����ͷ���
// ��ѡ���ij����������е������s_dev=0����������������ؿ�ָ���˳�������ͽ���
// ���϶�ȡ�ij�������Ϣ�ӻ�������������Ƶ�������������Ӧ��ṹ�С����ͷŴ�Ŷ�ȡ��
// Ϣ�ĸ��ٻ���顣
122 lock_super(s);
123 if (!(bh = bread(dev,1))) {
124 s->s_dev=0;
125 free_super(s);
126 return NULL;
127 }
128 *((struct d_super_block *) s) =
129 *((struct d_super_block *) bh->b_data);
130 brelse(bh);
// �������Ǵ��豸dev�ϵõ����ļ�ϵͳ�ij����飬���ǿ�ʼ���������������Ч�Բ�����
// ���϶�ȡi�ڵ�λͼ������λͼ����Ϣ���������ȡ�ij�������ļ�ϵͳħ���ֶβ��ԣ�
// ˵���豸�ϲ�����ȷ���ļ�ϵͳ�����ͬ����һ�����ͷ�����ѡ���ij����������е����
// ����������ؿ�ָ���˳������ڸð�Linux�ںˣ�ֻ֧��MINIX�ļ�ϵͳ1.0�汾����ħ
// ����0x137f��
131 if (s->s_magic != SUPER_MAGIC) {
132 s->s_dev = 0;
133 free_super(s);
134 return NULL;
135 }
// ���濪ʼ��ȡ�豸��i�ڵ�λͼ������λͼ���ݡ����ȳ�ʼ���ڴ泬����ṹ��λͼ�ռ䡣
// Ȼ����豸�϶�ȡi�ڵ�λͼ������λͼ��Ϣ��������ڳ������Ӧ�ֶ��С�i�ڵ�λͼ
// �������豸��2�ſ鿪ʼ�������У���ռ��s_imap_blocks���顣����λͼ��i�ڵ�λ
// ͼ���ڿ�ĺ������У���ռ��s_zmap_blocks���顣
136 for (i=0;i<I_MAP_SLOTS;i++) // ��ʼ��������
137 s->s_imap[i] = NULL;
138 for (i=0;i<Z_MAP_SLOTS;i++)
139 s->s_zmap[i] = NULL;
140 block=2;
141 for (i=0 ; i < s->s_imap_blocks ; i++) // ��ȡ�豸��i�ڵ�λͼ��
142 if (s->s_imap[i]=bread(dev,block))
143 block++;
144 else
145 break;
146 for (i=0 ; i < s->s_zmap_blocks ; i++) // ��ȡ�豸������λͼ��
147 if (s->s_zmap[i]=bread(dev,block))
148 block++;
149 else
150 break;
// ���������λͼ����������λͼӦ��ռ�е���������˵���ļ�ϵͳλͼ��Ϣ�����⣬����
// ���ʼ��ʧ�ܡ����ֻ���ͷ�ǰ�����벢ռ�õ�������Դ�����ͷ�i�ڵ�λͼ������λͼ
// ռ�õĸ��ٻ���顢�ͷ�����ѡ���ij���������������ó�����������ؿ�ָ���˳���
151 if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
152 for(i=0;i<I_MAP_SLOTS;i++) // �ͷ�λͼռ�õĸ��ٻ���顣
153 brelse(s->s_imap[i]);
154 for(i=0;i<Z_MAP_SLOTS;i++)
155 brelse(s->s_zmap[i]);
156 s->s_dev=0; // �ͷ�ѡ���ij����������
157 free_super(s); // ���������
158 return NULL;
159 }
// ����һ�гɹ������⣬���ڶ����������i�ڵ�ĺ�������������豸�����е�i�ڵ��Ѿ�
// ȫ��ʹ�ã�����Һ����᷵��0ֵ�����0��i�ڵ��Dz����õģ��������ォλͼ�е�1��
// ����ͱ���λ����Ϊ1���Է�ֹ�ļ�ϵͳ����0��i�ڵ㡣ͬ���ĵ�����Ҳ������λͼ��
// ���λ����Ϊ1������������ó����飬�����س�����ָ�롣
160 s->s_imap[0]->b_data[0] |= 1;
161 s->s_zmap[0]->b_data[0] |= 1;
162 free_super(s);
163 return s;
164 }
165
//// ж���ļ�ϵͳ��ϵͳ���ã���
// ����dev_name���ļ�ϵͳ�����豸���豸�ļ�����
// �ú������ȸ��ݲ��������Ŀ��豸�ļ�������豸�ţ�Ȼ��λ�ļ�ϵͳ�������е���Ӧ��
// �Σ��ͷų������λͼռ�õĻ���飬���Ը��豸ִ�и��ٻ������豸�����ݵ�ͬ��������
// ��ж�ز����ɹ���0�����س����롣
166 int sys_umount(char * dev_name)
167 {
168 struct m_inode * inode;
169 struct super_block * sb;
170 int dev;
171
// ���ȸ����豸�ļ����ҵ���Ӧ��i�ڵ㣬��ȡ���е��豸�š��豸�ļ��������豸���豸��
// �DZ�������i�ڵ��i_zone[0]�еġ� �μ�����namei.c������ϵͳ����sys_mknod()�Ĵ�
// ���445�С����⣬�����ļ�ϵͳ��Ҫ����ڿ��豸�ϣ����������ǿ��豸�ļ�����Ż�
// �������i�ڵ�dev_i�����س����롣
172 if (!(inode=namei(dev_name)))
173 return -ENOENT;
174 dev = inode->i_zone[0];
175 if (!S_ISBLK(inode->i_mode)) {
176 iput(inode); // fs/inode.c����150��
177 return -ENOTBLK;
178 }
// OK����������Ϊ�˵õ��豸�Ŷ�ȡ�õ�i�ڵ������������ʹ�����������Żظ��豸�ļ�
// ��i�ڵ㡣�������������һ��ж�ظ��ļ�ϵͳ�������Ƿ����㡣����豸���Ǹ��ļ�ϵͳ��
// ���ܱ�ж�أ�����æ�����š�
179 iput(inode);
180 if (dev==ROOT_DEV)
181 return -EBUSY;
// ����ڳ��������û���ҵ����豸���ļ�ϵͳ�ij����飬�������ҵ����Ǹ��豸���ļ�ϵͳ
// û�а�װ�����س����롣�����������ָ���ı���װ����i�ڵ㲢û����λ�䰲װ��־
// i_mount������ʾ������Ϣ�� Ȼ�����һ��i�ڵ���������Ƿ��н�����ʹ�ø��豸�ϵ���
// �����������æ�����롣
182 if (!(sb=get_super(dev)) || !(sb->s_imount))
183 return -ENOENT;
184 if (!sb->s_imount->i_mount)
185 printk("Mounted inode has i_mount=0\n");
186 for (inode=inode_table+0 ; inode<inode_table+NR_INODE ; inode++)
187 if (inode->i_dev==dev && inode->i_count)
188 return -EBUSY;
// ���ڸ��豸���ļ�ϵͳ��ж���������õ����㣬������ǿ��Կ�ʼʵʩ������ж�ز����ˡ�
// ���ȸ�λ����װ����i�ڵ�İ�װ��־���ͷŸ�i�ڵ㡣Ȼ���ó������б���װi�ڵ��ֶ�
// Ϊ�գ����Ż��豸�ļ�ϵͳ�ĸ�i�ڵ㣬�����ó������б���װϵͳ��i�ڵ�ָ��Ϊ�ա�
189 sb->s_imount->i_mount=0;
190 iput(sb->s_imount);
191 sb->s_imount = NULL;
192 iput(sb->s_isup);
193 sb->s_isup = NULL;
// ��������ͷŸ��豸�ϵij������Լ�λͼռ�õĸ��ٻ���飬���Ը��豸ִ�и��ٻ�������
// �������ݵ�ͬ��������Ȼ��0��ж�سɹ�����
194 put_super(dev);
195 sync_dev(dev);
196 return 0;
197 }
198
//// ��װ�ļ�ϵͳ��ϵͳ���ã���
// ����dev_name���豸�ļ�����dir_name�ǰ�װ����Ŀ¼����rw_flag����װ�ļ�ϵͳ�Ŀ�
// ��д��־���������صĵط�������һ��Ŀ¼�������Ҷ�Ӧ��i�ڵ�û�б���������ռ�á�
// �������ɹ���0�����س����š�
199 int sys_mount(char * dev_name, char * dir_name, int rw_flag)
200 {
201 struct m_inode * dev_i, * dir_i;
202 struct super_block * sb;
203 int dev;
204
// ���ȸ����豸�ļ����ҵ���Ӧ��i�ڵ㣬��ȡ�����е��豸�š����ڿ������豸�ļ����豸
// ������i�ڵ��i_zone[0]�С����⣬�����ļ�ϵͳ�����ڿ��豸�У����������ǿ��豸
// �ļ�����Żظ�ȡ�õ�i�ڵ�dev_i�����س����롣
205 if (!(dev_i=namei(dev_name)))
206 return -ENOENT;
207 dev = dev_i->i_zone[0];
208 if (!S_ISBLK(dev_i->i_mode)) {
209 iput(dev_i);
210 return -EPERM;
211 }
// OK����������Ϊ�˵õ��豸�Ŷ�ȡ�õ�i�ڵ�dev_i�����������ʹ�����������Żظ���
// ���ļ���i�ڵ㡣�������������һ���ļ�ϵͳ��װ����Ŀ¼���Ƿ���Ч�����Ǹ��ݸ�����
// Ŀ¼�ļ����ҵ���Ӧ��i�ڵ� dir_i�� �����i�ڵ�����ü�����Ϊ1�������������ã���
// ���߸�i�ڵ�Ľڵ���Ǹ��ļ�ϵͳ�Ľڵ��1����Żظ�i�ڵ㷵�س����롣���⣬���
// �ýڵ㲻��һ��Ŀ¼�ļ��ڵ㣬��Ҳ�Żظ�i�ڵ㣬���س����롣��Ϊ�ļ�ϵͳֻ�ܰ�װ��
// һ��Ŀ¼���ϡ�
212 iput(dev_i);
213 if (!(dir_i=namei(dir_name)))
214 return -ENOENT;
215 if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
216 iput(dir_i);
217 return -EBUSY;
218 }
219 if (!S_ISDIR(dir_i->i_mode)) { // ��װ����Ҫ��һ��Ŀ¼����
220 iput(dir_i);
221 return -EPERM;
222 }
// ���ڰ�װ��Ҳ�����ϣ����ǿ�ʼ��ȡҪ��װ�ļ�ϵͳ�ij�������Ϣ����������������ʧ
// �ܣ���Żظð�װ��i�ڵ�dir_i�����س����롣һ���ļ�ϵͳ�ij���������ȴӳ������
// �н���������������ڳ�������оʹ��豸�϶�ȡ��
223 if (!(sb=read_super(dev))) {
224 iput(dir_i);
225 return -EBUSY;
226 }
// �ڵõ����ļ�ϵͳ������֮�����Ƕ����Ƚ��м��һ���������Ҫ����װ���ļ�ϵͳ�Ѿ�
// ��װ�������ط�����Żظ�i�ڵ㣬���س����롣�����Ҫ��װ����i�ڵ��Ѿ���װ���ļ�
// ϵͳ����װ��־�Ѿ���λ������Żظ�i�ڵ㣬Ҳ���س����롣
227 if (sb->s_imount) {
228 iput(dir_i);
229 return -EBUSY;
230 }
231 if (dir_i->i_mount) {
232 iput(dir_i);
233 return -EPERM;
234 }
// ������ñ���װ�ļ�ϵͳ������ġ�����װ��i�ڵ㡱�ֶ�ָ��װ����Ŀ¼����i�ڵ㡣
// �����ð�װλ��i�ڵ�İ�װ��־�ͽڵ����ı�־��Ȼ��0����װ�ɹ�����
235 sb->s_imount=dir_i;
236 dir_i->i_mount=1;
237 dir_i->i_dirt=1;/* NOTE! we don't iput(dir_i) */ /*ע��!����û��iput(dir_i)*/
238 return 0; /* we do that in umount */ /* �⽫��umount�ڲ��� */
239 }
240
//// ��װ���ļ�ϵͳ��
// �ú�������ϵͳ��ʼ��������һ���֡��������ȳ�ʼ���ļ�������file_table[]�ͳ������
// �����飩��Ȼ���ȡ���ļ�ϵͳ�����飬��ȡ���ļ�ϵͳ��i�ڵ㡣 ���ͳ�Ʋ���ʾ������
// ��ϵͳ�ϵĿ�����Դ�����п����Ϳ���i�ڵ������� �ú�������ϵͳ�������г�ʼ������ʱ
// ��sys_setup()�����ã�blk_drv/hd.c��157�У���
241 void mount_root(void)
242 {
243 int i,free;
244 struct super_block * p;
245 struct m_inode * mi;
246
// ������i�ڵ�ṹ����32�ֽڣ������ͣ�������ж����ڷ�ֹ�Ĵ���ʱ���ֲ�һ�������
247 if (32 != sizeof (struct d_inode))
248 panic("bad i-node size");
// ���ȳ�ʼ���ļ������飨��64���ϵͳͬʱֻ�ܴ�64���ļ����ͳ�����������ォ��
// ���ļ��ṹ�е����ü�������Ϊ0����ʾ���У������ѳ�������и���ṹ���豸�ֶγ�ʼ
// ��Ϊ0��Ҳ��ʾ���У���������ļ�ϵͳ�����豸�����̵Ļ�������ʾ��������ļ�ϵͳ�̣�
// �����س����������ȴ�������
249 for(i=0;i<NR_FILE;i++) // ��ʼ���ļ�����
250 file_table[i].f_count=0;
251 if (MAJOR(ROOT_DEV) == 2) { // ��ʾ������ļ�ϵͳ�̡�
252 printk("Insert root floppy and press ENTER");
253 wait_for_keypress();
254 }
255 for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
256 p->s_dev = 0; // ��ʼ�����������
257 p->s_lock = 0;
258 p->s_wait = NULL;
259 }
// �������ϡ����⡱�ij�ʼ������֮�����ǿ�ʼ��װ���ļ�ϵͳ�����ǴӸ��豸�϶�ȡ�ļ�
// ϵͳ�����飬��ȡ���ļ�ϵͳ�ĸ�i�ڵ㣨1�Žڵ㣩���ڴ�i�ڵ���е�ָ�롣�������
// �豸�ϳ�����ʧ�ܻ�ȡ���ڵ�ʧ�ܣ�����ʾ��Ϣ��ͣ����
260 if (!(p=read_super(ROOT_DEV)))
261 panic("Unable to mount root");
262 if (!(mi=iget(ROOT_DEV,ROOT_INO))) // ��fs.h��ROOT_INO����Ϊ1��
263 panic("Unable to read root i-node");
// �������ǶԳ������i�ڵ�������á��Ѹ�i�ڵ����ô�������3�Ρ���Ϊ����266����
// Ҳ�����˸�i�ڵ㡣���⣬iget() ������i�ڵ����ü����ѱ�����Ϊ1��Ȼ���øó������
// ����װ�ļ�ϵͳi�ڵ�ͱ���װ��i�ڵ��ֶ�Ϊ��i�ڵ㡣�����õ�ǰ���̵ĵ�ǰ����Ŀ¼
// ��Ŀ¼i�ڵ㡣��ʱ��ǰ������1�Ž��̣�init���̣���
264 mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
/* ע�⣡�����Ͻ������ѱ�������4�Σ�������1�� */
265 p->s_isup = p->s_imount = mi;
266 current->pwd = mi;
267 current->root = mi;
// Ȼ�����ǶԸ��ļ�ϵͳ�ϵ���Դ��ͳ�ƹ�����ͳ�Ƹ��豸�Ͽ��п����Ϳ���i�ڵ���������
// ��i���ڳ������б������豸����������Ȼ���������λͼ����Ӧ����λ��ռ�����ͳ
// �Ƴ����п���������꺯��set_bit()ֻ���ڲ��Ա���λ���������ñ���λ��"i&8191" ����
// ȡ��i�ڵ���ڵ�ǰλͼ���ж�Ӧ�ı���λƫ��ֵ��"i>>13" �ǽ�i����8192��Ҳ����һ��
// ���̿�����ı���λ����
268 free=0;
269 i=p->s_nzones;
270 while (-- i >= 0)
271 if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
272 free++;
// ����ʾ���豸�Ͽ���������/��������֮��������ͳ���豸�Ͽ���i�ڵ�����������i
// ���ڳ������б������豸��i�ڵ�����+1����1�ǽ�0�ڵ�Ҳͳ�ƽ�ȥ��Ȼ�����i�ڵ�λ
// ͼ����Ӧ����λ��ռ��������������i�ڵ������������ʾ�豸�Ͽ��ÿ���i�ڵ�����i
// �ڵ�������
273 printk("%d/%d free blocks\n\r",free,p->s_nzones);
274 free=0;
275 i=p->s_ninodes+1;
276 while (-- i >= 0)
277 if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
278 free++;
279 printk("%d/%d free inodes\n\r",free,p->s_ninodes);
280 }
281
1 /*
2 * linux/fs/namei.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * Some corrections by tytso.
9 */
10
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݵȡ�
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14
15 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
16 #include <fcntl.h> // �ļ�����ͷ�ļ����ļ������������IJ������Ƴ������ŵĶ��塣
17 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
18 #include <const.h> // ��������ͷ�ļ���Ŀǰ������i�ڵ���i_mode�ֶεĸ���־λ��
19 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
20
// ���ļ������Ҷ�Ӧi�ڵ���ڲ�������
21 static struct m_inode * _namei(const char * filename, struct m_inode * base,
22 int follow_links);
23
// ��������Ҳ����ʽ�Ƿ��������һ������ʹ�÷�����������������һ����ʵ��������������
// �����±�����ʾ�����������a[b]����ֵ��ͬ��ʹ��������ָ�루��ַ�����ϸ���ƫ�Ƶ�ַ
// ����ʽ��ֵ *(a + b)��ͬʱ��֪��a[b]Ҳ���Ա�ʾ��b[a]����ʽ����˶����ַ���������ʽ
// Ϊ "LoveYou"[2]������2["LoveYou"]���͵�ͬ��*("LoveYou" + 2)�����⣬�ַ���"LoveYou"
// ���ڴ��б��洢��λ�þ������ַ�����������"LoveYou"[2]��ֵ���Ǹ��ַ���������ֵΪ2
// ���ַ�"v"����Ӧ��ASCII��ֵ0x76�����ð˽��Ʊ�ʾ����0166����C�����У��ַ�Ҳ������
// ��ASCII��ֵ����ʾ�����������ַ���ASCII��ֵǰ���һ����б�ܡ������ַ� "v"���Ա�ʾ
// ��"\x76"����"\166"����˶��ڲ�����ʾ���ַ�������ASCII��ֵΪ0x00--0x1f�Ŀ����ַ���
// �Ϳ�����ASCII��ֵ����ʾ��
//
// �����Ƿ���ģʽ�ꡣx��ͷ�ļ�include/fcntl.h�е�7�п�ʼ������ļ����ʣ�����־��
// ���������ļ����ʱ�־x��ֵ������˫�����ж�Ӧ����ֵ��˫��������4���˽�����ֵ��ʵ
// �ʱ�ʾ4�������ַ�����"\004\002\006\377"���ֱ��ʾ����д��ִ�е�Ȩ��Ϊ: r��w��rw
// ��wxrwxrwx�����ҷֱ��Ӧx������ֵ0--3�� ���磬���xΪ2����ú귵�ذ˽���ֵ006��
// ��ʾ�ɶ���д��rw�������⣬����O_ACCMODE = 00003��������ֵx�������롣
24 #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
25
26 /*
27 * comment out this line if you want names > NAME_LEN chars to be
28 * truncated. Else they will be disallowed.
29 */
/*
* ��������ļ������� > NAME_LEN�����ַ����ص����ͽ����涨��ע�͵���
*/
30 /* #define NO_TRUNCATE */
31
32 #define MAY_EXEC 1 // ��ִ��(�ɽ���)��
33 #define MAY_WRITE 2 // ���
34 #define MAY_READ 4 // �ɶ���
35
36 /*
37 * permission()
38 *
39 * is used to check for read/write/execute permissions on a file.
40 * I don't know if we should look at just the euid or both euid and
41 * uid, but that should be easily changed.
42 */
/*
* permission()
*
* �ú������ڼ��һ���ļ��Ķ�/д/ִ��Ȩ�ޡ��Ҳ�֪���Ƿ�ֻ����euid��
* ������Ҫ���euid��uid���ߣ�������������ġ�
*/
//// ����ļ���������Ȩ�ޡ�
// ������inode - �ļ���i�ڵ�ָ�룻mask - �������������롣
// ���أ��������ɷ���1������0��
43 static int permission(struct m_inode * inode,int mask)
44 {
45 int mode = inode->i_mode; // �ļ��������ԡ�
46
47 /* special case: not even root can read/write a deleted file */
/* �����������ʹ�dz����û���root��Ҳ���ܶ�/дһ���ѱ�ɾ�����ļ� */
// ���i�ڵ��ж�Ӧ���豸������i�ڵ�����Ӽ���ֵ����0����ʾ���ļ��ѱ�ɾ�����ء�
// ����������̵���Ч�û�id��euid����i�ڵ���û�id��ͬ����ȡ�ļ������ķ���Ȩ�ޡ�
// ����������̵���Ч��id��egid����i�ڵ����id��ͬ����ȡ���û��ķ���Ȩ�ޡ�
48 if (inode->i_dev && !inode->i_nlinks)
49 return 0;
50 else if (current->euid==inode->i_uid)
51 mode >>= 6;
52 else if (in_group_p(inode->i_gid))
53 mode >>= 3;
// ����ж������ȡ�ĵķ���Ȩ������������ͬ�������dz����û�����1������0��
54 if (((mode & mask & 0007) == mask) || suser())
55 return 1;
56 return 0;
57 }
58
59 /*
60 * ok, we cannot use strncmp, as the name is not in our data space.
61 * Thus we'll have to use match. No big problem. Match also makes
62 * some sanity tests.
63 *
64 * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
65 */
/*
* ok�����Dz���ʹ��strncmp�ַ����ȽϺ�������Ϊ���Ʋ������ǵ����ݿռ�
* �������ں˿ռ䣩�� �������ֻ��ʹ�� match()�����ⲻ��match()ͬ��
* Ҳ����һЩ�����IJ��ԡ�
*
* ע�⣡��strncmp��ͬ����match()�ɹ�ʱ����1��ʧ��ʱ����0��
*/
//// ָ�������ַ����ȽϺ�����
// ������len - �Ƚϵ��ַ������ȣ�name - �ļ���ָ�룻de - Ŀ¼��ṹ��
// ���أ���ͬ����1����ͬ����0��
// ��68���϶�����һ���ֲ��Ĵ�������same���ñ�������������eax�Ĵ����У��Ա��ڸ�Ч
// ���ʡ�
66 static int match(int len,const char * name,struct dir_entry * de)
67 {
68 register int same __asm__("ax");
69
// �����жϺ�����������Ч�ԡ����Ŀ¼��ָ��գ�����Ŀ¼��i�ڵ����0������Ҫ�Ƚϵ�
// �ַ������ȳ����ļ������ȣ���0����ƥ�䣩������Ƚϵij���len����0����Ŀ¼��
// ���ļ����ĵ�1���ַ��� '.'������ֻ����ôһ���ַ�����ô���Ǿ���Ϊ����ͬ�ģ���˷�
// ��1��ƥ�䣩�����Ҫ�Ƚϵij���lenС��NAME_LEN������Ŀ¼�����ļ������ȳ���len��
// ��Ҳ����0����ƥ�䣩��
// ��75���϶�Ŀ¼�����ļ��������Ƿ� len ���жϷ����Ǽ�� name[len] �Ƿ�ΪNULL��
// �����ȳ���len����name[len]������һ������NULL����ͨ�ַ��������ڳ���Ϊlen���ַ�
// ��name���ַ�name[len]��Ӧ����NULL��
70 if (!de || !de->inode || len > NAME_LEN)
71 return 0;
72 /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
/* "" ���� "." ������ ---> �������ܴ����� "/usr/lib//libc.a" ������·���� */
73 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
74 return 1;
75 if (len < NAME_LEN && de->name[len])
76 return 0;
// Ȼ��ʹ��Ƕ���������п��ٱȽϲ������������û����ݿռ䣨fs�Σ�ִ���ַ����ıȽ�
// ������%0 - eax���ȽϽ��same����%1 - eax��eax��ֵ0����%2 - esi������ָ�룩��
// %3 - edi��Ŀ¼����ָ�룩��%4 - ecx(�Ƚϵ��ֽڳ���ֵlen)��
77 __asm__("cld\n\t" // �巽���־λ��
78 "fs ; repe ; cmpsb\n\t" // �û��ռ�ִ��ѭ���Ƚ�[esi++]��[edi++]������
79 "setz %%al" // ���ȽϽ��һ����zf=0������al=1��same=eax����
80 :"=a" (same)
81 :"" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
82 :"cx","di","si");
83 return same; // ���رȽϽ����
84 }
85
86 /*
87 * find_entry()
88 *
89 * finds an entry in the specified directory with the wanted name. It
90 * returns the cache buffer in which the entry was found, and the entry
91 * itself (as a parameter - res_dir). It does NOT read the inode of the
92 * entry - you'll have to do that yourself if you want to.
93 *
94 * This also takes care of the few special cases due to '..'-traversal
95 * over a pseudo-root and a mount point.
96 */
/*
* find_entry()
*
* ��ָ��Ŀ¼��Ѱ��һ��������ƥ���Ŀ¼�����һ�������ҵ�Ŀ¼��ĸ���
* ������Լ�Ŀ¼�������Ϊһ������ - res_dir�����ú���������ȡĿ¼��
* ��i�ڵ� - �����Ҫ�Ļ����Լ�������
*
* ������'..'Ŀ¼�����ڲ����ڼ�Ҳ��Լ�����������ֱ��� - �����Խ
* һ��α��Ŀ¼�Լ���װ�㡣
*/
//// ����ָ��Ŀ¼���ļ�����Ŀ¼�
// ������*dir - ָ��Ŀ¼i�ڵ��ָ�룻name - �ļ�����namelen - �ļ������ȣ�
// �ú�����ָ��Ŀ¼�����ݣ��ļ���������ָ���ļ�����Ŀ¼�����ָ���ļ�����'..'��
// ������ݵ�ǰ���е�������ý�������������ں�����������ָ���ָ������ã����
// ��linux/sched.c��151��ǰ��ע�͡�
// ���أ��ɹ��������ٻ�����ָ�룬����*res_dir�����ص�Ŀ¼��ṹָ�롣ʧ����
// ��ָ��NULL��
97 static struct buffer_head * find_entry(struct m_inode ** dir,
98 const char * name, int namelen, struct dir_entry ** res_dir)
99 {
100 int entries;
101 int block,i;
102 struct buffer_head * bh;
103 struct dir_entry * de;
104 struct super_block * sb;
105
// ͬ����������һ����Ҳ��Ҫ�Ժ�����������Ч�Խ����жϺ���֤�����������ǰ���30��
// �����˷��ų���NO_TRUNCATE����ô����ļ������ȳ������NAME_LEN�����账����
// ���û�ж����NO_TRUNCATE����ô���ļ������ȳ������NAME_LENʱ�ض�֮��
106 #ifdef NO_TRUNCATE
107 if (namelen > NAME_LEN)
108 return NULL;
109 #else
110 if (namelen > NAME_LEN)
111 namelen = NAME_LEN;
112 #endif
// ���ȼ��㱾Ŀ¼��Ŀ¼������entries�� Ŀ¼i�ڵ� i_size�ֶ��к��б�Ŀ¼����������
// ���ȣ���������һ��Ŀ¼��ij��ȣ�16�ֽڣ����ɵõ���Ŀ¼��Ŀ¼������Ȼ���ÿշ���
// Ŀ¼��ṹָ�롣
113 entries = (*dir)->i_size / (sizeof (struct dir_entry));
114 *res_dir = NULL;
// ���������Ƕ�Ŀ¼���ļ�����'..'���������������������ǰ����ָ���ĸ�i�ڵ����
// ��������ָ����Ŀ¼����˵�����ڱ�������˵�����Ŀ¼��������α��Ŀ¼��������ֻ�ܷ�
// �ʸ�Ŀ¼�е�������ܺ��˵��丸Ŀ¼��ȥ��Ҳ�����ڸý��̱�Ŀ¼����ͬ���ļ�ϵͳ�ĸ�
// Ŀ¼�����������Ҫ���ļ�����Ϊ'.'��
// ���������Ŀ¼��i�ڵ�ŵ���ROOT_INO��1�ţ��Ļ���˵��ȷʵ���ļ�ϵͳ�ĸ�i�ڵ㡣
// ��ȡ�ļ�ϵͳ�ij����顣�������װ����i�ڵ���ڣ����ȷŻ�ԭi�ڵ㣬Ȼ��Ա���װ��
// ��i�ڵ���д���������������*dirָ��ñ���װ����i�ڵ㣻���Ҹ�i�ڵ����������1��
// ���������������������ĵؽ����ˡ�͵������������:)
115 /* check for '..', as we might have to do some "magic" for it */
/* ���Ŀ¼�� '..'����Ϊ���ǿ�����Ҫ������������ */
116 if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
117 /* '..' in a pseudo-root results in a faked '.' (just change namelen) */
/* α���е� '..' ��ͬһ���� '.'��ֻ��ı����ֳ��ȣ� */
118 if ((*dir) == current->root)
119 namelen=1;
120 else if ((*dir)->i_num == ROOT_INO) {
121 /* '..' over a mount-point results in 'dir' being exchanged for the mounted
122 directory-inode. NOTE! We set mounted, so that we can iput the new dir */
/* ��һ����װ���ϵ� '..' ������Ŀ¼����������װ�ļ�ϵͳ��Ŀ¼i�ڵ��ϡ�ע�⣡
��������������mounted��־����������ܹ��Żظ���Ŀ¼ */
123 sb=get_super((*dir)->i_dev);
124 if (sb->s_imount) {
125 iput(*dir);
126 (*dir)=sb->s_imount;
127 (*dir)->i_count++;
128 }
129 }
130 }
// �������ǿ�ʼ��������������ָ���ļ�����Ŀ¼����ʲô�ط������������Ҫ��ȡĿ¼����
// �ݣ���ȡ��Ŀ¼i�ڵ��Ӧ���豸�������е����ݿ飨���飩��Ϣ����Щ����Ŀ�ű�
// ����i�ڵ�ṹ�� i_zone[9]�����С�������ȡ���е�1����š����Ŀ¼i�ڵ�ָ��ĵ�
// һ��ֱ�Ӵ��̿��Ϊ0����˵����Ŀ¼��Ȼ�������ݣ��ⲻ���������Ƿ���NULL�˳�������
// ���Ǿʹӽڵ������豸��ȡָ����Ŀ¼�����ݿ顣��Ȼ��������ɹ�����Ҳ����NULL�˳���
131 if (!(block = (*dir)->i_zone[0]))
132 return NULL;
133 if (!(bh = bread((*dir)->i_dev,block)))
134 return NULL;
// ��ʱ���Ǿ��������ȡ��Ŀ¼i�ڵ����ݿ�������ƥ��ָ���ļ�����Ŀ¼�������deָ
// ����е����ݿ鲿�֣����ڲ�����Ŀ¼��Ŀ¼�����������£�ѭ��ִ������������i��
// Ŀ¼�е�Ŀ¼�������ţ���ѭ����ʼʱ��ʼ��Ϊ0��
135 i = 0;
136 de = (struct dir_entry *) bh->b_data;
137 while (i < entries) {
// �����ǰĿ¼�����ݿ��Ѿ������꣬��û���ҵ�ƥ���Ŀ¼����ͷŵ�ǰĿ¼�����ݿ顣
// �ٶ���Ŀ¼����һ�����顣�����Ϊ�գ���ֻҪ��û��������Ŀ¼�е�����Ŀ¼���
// �����ÿ飬������Ŀ¼����һ���顣���ÿ鲻�գ����� de ָ������ݿ飬Ȼ��������
// ��������������141����i/DIR_ENTRIES_PER_BLOCK�ɵõ���ǰ������Ŀ¼������Ŀ¼��
// ���еĿ�ţ���bmap()������inode.c����142�У���ɼ�������豸�϶�Ӧ������š�
138 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
139 brelse(bh);
140 bh = NULL;
141 if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
142 !(bh = bread((*dir)->i_dev,block))) {
143 i += DIR_ENTRIES_PER_BLOCK;
144 continue;
145 }
146 de = (struct dir_entry *) bh->b_data;
147 }
// ����ҵ�ƥ���Ŀ¼��Ļ����ظ�Ŀ¼��ṹָ��de��Ŀ¼��i�ڵ�ָ��*dir��
// ����Ŀ¼�����ݿ�ָ��bh�����˳����������������Ŀ¼�����ݿ��бȽ���һ��Ŀ¼�
148 if (match(namelen,name,de)) {
149 *res_dir = de;
150 return bh;
151 }
152 de++;
153 i++;
154 }
// ���ָ��Ŀ¼�е�����Ŀ¼��������û���ҵ���Ӧ��Ŀ¼����ͷ�Ŀ¼������
// �飬���NULL��ʧ�ܣ���
155 brelse(bh);
156 return NULL;
157 }
158
159 /*
160 * add_entry()
161 *
162 * adds a file entry to the specified directory, using the same
163 * semantics as find_entry(). It returns NULL if it failed.
164 *
165 * NOTE!! The inode part of 'de' is left at 0 - which means you
166 * may not sleep between calling this and putting something into
167 * the entry, as someone else might have used it while you slept.
168 */
/*
* add_entry()
* ʹ����find_entry()ͬ���ķ�������ָ��Ŀ¼������һָ���ļ�����Ŀ
* ¼����ʧ����NULL��
*
* ע�⣡��'de'��ָ��Ŀ¼��ṹָ�룩��i�ڵ㲿�ֱ�����Ϊ0 - ���
* ʾ�ڵ��øú�������Ŀ¼����������Ϣ֮�䲻��ȥ˯�ߡ� ��Ϊ���˯�ߣ�
* ��ô������(����)���ܻ�ʹ���˸�Ŀ¼�
*/
//// ����ָ����Ŀ¼���ļ�������Ŀ¼�
// ������dir - ָ��Ŀ¼��i�ڵ㣻name - �ļ�����namelen - �ļ������ȣ�
// ���أ����ٻ�����ָ�룻res_dir - ���ص�Ŀ¼��ṹָ�룻
169 static struct buffer_head * add_entry(struct m_inode * dir,
170 const char * name, int namelen, struct dir_entry ** res_dir)
171 {
172 int block,i;
173 struct buffer_head * bh;
174 struct dir_entry * de;
175
// ͬ����������һ����Ҳ��Ҫ�Ժ�����������Ч�Խ����жϺ���֤�����������ǰ���30��
// �����˷��ų���NO_TRUNCATE����ô����ļ������ȳ������NAME_LEN�����账����
// ���û�ж����NO_TRUNCATE����ô���ļ������ȳ������NAME_LENʱ�ض�֮��
176 *res_dir = NULL; // ���ڷ���Ŀ¼��ṹָ�롣
177 #ifdef NO_TRUNCATE
178 if (namelen > NAME_LEN)
179 return NULL;
180 #else
181 if (namelen > NAME_LEN)
182 namelen = NAME_LEN;
183 #endif
// �������ǿ�ʼ��������ָ��Ŀ¼������һ��ָ���ļ�����Ŀ¼����������Ҫ�ȶ�ȡĿ¼
// �����ݣ���ȡ��Ŀ¼i�ڵ��Ӧ���豸�������е����ݿ飨���飩��Ϣ����Щ����Ŀ�
// �ű�����i�ڵ�ṹ�� i_zone[9]�����С�������ȡ���е�1����š����Ŀ¼i�ڵ�ָ��
// �ĵ�һ��ֱ�Ӵ��̿��Ϊ0����˵����Ŀ¼��Ȼ�������ݣ��ⲻ���������Ƿ���NULL�˳���
// �������Ǿʹӽڵ������豸��ȡָ����Ŀ¼�����ݿ顣��Ȼ��������ɹ�����Ҳ����NULL
// �˳������⣬��������ṩ���ļ������ȵ���0����Ҳ����NULL�˳���
184 if (!namelen)
185 return NULL;
186 if (!(block = dir->i_zone[0]))
187 return NULL;
188 if (!(bh = bread(dir->i_dev,block)))
189 return NULL;
// ��ʱ���Ǿ������Ŀ¼i�ڵ����ݿ���ѭ���������δʹ�õĿ�Ŀ¼�������Ŀ¼��ṹ
// ָ��deָ����е����ݿ鲿�֣�����һ��Ŀ¼�������i��Ŀ¼�е�Ŀ¼�������ţ�
// ��ѭ����ʼʱ��ʼ��Ϊ0��
190 i = 0;
191 de = (struct dir_entry *) bh->b_data;
192 while (1) {
// �����ǰĿ¼�����ݿ��Ѿ�������ϣ�����û���ҵ���Ҫ�Ŀ�Ŀ¼����ͷŵ�ǰĿ¼����
// �ݿ飬�ٶ���Ŀ¼����һ�����顣�����Ӧ�����鲻���ھʹ���һ�顣����ȡ����
// ��ʧ���ؿա�����˴ζ�ȡ�Ĵ����������ݷ��صĻ����ָ��Ϊ�գ�˵���������
// ��������Ϊ�����ڶ��´����Ŀտ飬���Ŀ¼������ֵ����һ�������������ɵ�Ŀ¼����
// DIR_ENTRIES_PER_BLOCK�����������ÿ鲢��������������˵���¶���Ŀ�����Ŀ¼�����ݣ�
// ������Ŀ¼��ṹָ��deָ��ÿ�Ļ�������ݲ��֣�Ȼ�������м�������������196��
// �ϵ� i/DIR_ENTRIES_PER_BLOCK �ɼ���õ���ǰ������Ŀ¼��i ����Ŀ¼�ļ��еĿ�ţ�
// ��create_block()������inode.c����147�У���ɶ�ȡ�������豸�϶�Ӧ�����顣
193 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
194 brelse(bh);
195 bh = NULL;
196 block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
197 if (!block)
198 return NULL;
199 if (!(bh = bread(dir->i_dev,block))) { // �����������ÿ������
200 i += DIR_ENTRIES_PER_BLOCK;
201 continue;
202 }
203 de = (struct dir_entry *) bh->b_data;
204 }
// �����ǰ��������Ŀ¼�����i����Ŀ¼�ṹ��С���ij���ֵ�Ѿ������˸�Ŀ¼i�ڵ���Ϣ
// ��ָ����Ŀ¼���ݳ���ֵ i_size ����˵������Ŀ¼�ļ�������û������ɾ���ļ����µĿ�
// Ŀ¼��������ֻ�ܰ���Ҫ���ӵ���Ŀ¼��ӵ�Ŀ¼�ļ����ݵ�ĩ�˴������ǶԸô�Ŀ
// ¼��������ã��ø�Ŀ¼���i�ڵ�ָ��Ϊ�գ��������¸�Ŀ¼�ļ��ij���ֵ������һ��Ŀ
// ¼��ij��ȣ���Ȼ������Ŀ¼��i�ڵ����ı�־���ٸ��¸�Ŀ¼�ĸı�ʱ��Ϊ��ǰʱ�䡣
205 if (i*sizeof(struct dir_entry) >= dir->i_size) {
206 de->inode=0;
207 dir->i_size = (i+1)*sizeof(struct dir_entry);
208 dir->i_dirt = 1;
209 dir->i_ctime = CURRENT_TIME;
210 }
// ����ǰ������Ŀ¼�� de ��i�ڵ�Ϊ�գ����ʾ�ҵ�һ����δʹ�õĿ���Ŀ¼��������ӵ�
// ��Ŀ¼����Ǹ���Ŀ¼����ʱ��Ϊ��ǰʱ�䣬�����û������������ļ�������Ŀ¼���
// �ļ����ֶΣ��ú��б�Ŀ¼�����Ӧ���ٻ�������ı�־�����ظ�Ŀ¼���ָ���Լ��ø�
// �ٻ�����ָ�룬�˳���
211 if (!de->inode) {
212 dir->i_mtime = CURRENT_TIME;
213 for (i=0; i < NAME_LEN ; i++)
214 de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
215 bh->b_dirt = 1;
216 *res_dir = de;
217 return bh;
218 }
219 de++; // �����Ŀ¼���Ѿ���ʹ�ã�����������һ��Ŀ¼�
220 i++;
221 }
// ������ִ�в��������Ҳ����Linus��д��δ���ʱ���ȸ���������find_entry()����
// �Ĵ��룬�����ijɱ�������J��
222 brelse(bh);
223 return NULL;
224 }
225
//// ���ҷ������ӵ�i�ڵ㡣
// ������dir - Ŀ¼i�ڵ㣻inode - Ŀ¼��i�ڵ㡣
// ���أ����ط������ӵ��ļ���i�ڵ�ָ�롣��������NULL��
226 static struct m_inode * follow_link(struct m_inode * dir, struct m_inode * inode)
227 {
228 unsigned short fs; // ������ʱ����fs�μĴ���ֵ��
229 struct buffer_head * bh;
230
// �����жϺ�����������Ч�ԡ����û�и���Ŀ¼i�ڵ㣬���Ǿ�ʹ�ý�������ṹ�����õ�
// ��i�ڵ㣬������������1�����û�и���Ŀ¼��i�ڵ㣬��Ż�Ŀ¼i�ڵ��NULL��
// ���ָ��Ŀ¼���һ���������ӣ���ֱ�ӷ���Ŀ¼���Ӧ��i�ڵ�inode��
231 if (!dir) {
232 dir = current->root;
233 dir->i_count++;
234 }
235 if (!inode) {
236 iput(dir);
237 return NULL;
238 }
239 if (!S_ISLNK(inode->i_mode)) {
240 iput(dir);
241 return inode;
242 }
// Ȼ��ȡfs�μĴ���ֵ��fsͨ��������ָ���������ݶε�ѡ���0x17�����fsû��ָ���û�
// ���ݶΣ����߸�����Ŀ¼��i�ڵ��1��ֱ�ӿ��ŵ���0�������Ƕ�ȡ��1��ֱ�ӿ������
// ��Ż�dir��inode����i�ڵ㲢����NULL�˳�������˵������fs��ָ���û����ݶΡ�����
// �����Ѿ��ɹ��ض�ȡ�������������Ŀ¼����ļ����ݣ������ļ������Ѿ��� bh ָ��Ļ���
// ���������С�ʵ���ϣ����������������н�����һ������ָ����ļ�·�����ַ�����
243 __asm__("mov %%fs,%0":"=r" (fs));
244 if (fs != 0x17 || !inode->i_zone[0] ||
245 !(bh = bread(inode->i_dev, inode->i_zone[0]))) {
246 iput(dir);
247 iput(inode);
248 return NULL;
249 }
// ��ʱ�����Ѿ�����Ҫ��������Ŀ¼���i�ڵ��ˣ����ǰ����Żء���������һ�����⣬�Ǿ�
// ���ں˺����������û����ݶ��Ǵ�����û����ݿռ��еģ���ʹ���� fs �μĴ��������û�
// �ռ䴫�����ݵ��ں˿ռ��С���������Ҫ����������ȴ���ں˿ռ��С����Ϊ����ȷ�ش���
// λ���ں��е��û����ݣ�������Ҫ��fs�μĴ�����ʱָ���ں˿ռ䣬����fs =0x10������
// ���ú�����������ٻָ�ԭfs��ֵ������ͷ���Ӧ����飬������ _namei()�����õ��ķ�
// ������ָ����ļ�i�ڵ㡣
250 iput(inode);
251 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
252 inode = _namei(bh->b_data,dir,0);
253 __asm__("mov %0,%%fs"::"r" (fs));
254 brelse(bh);
255 return inode;
256 }
257
258 /*
259 * get_dir()
260 *
261 * Getdir traverses the pathname until it hits the topmost directory.
262 * It returns NULL on failure.
263 */
/*
* get_dir()
*
* �ú������ݸ�����·��������������ֱ���ﵽ��˵�Ŀ¼��
* ���ʧ����NULL��
*/
//// ��ָ��Ŀ¼��ʼ��Ѱָ��·������Ŀ¼�����ļ�������i�ڵ㡣
// ������pathname - ·������inode - ָ����ʼĿ¼��i�ڵ㡣
// ���أ�Ŀ¼���ļ���i�ڵ�ָ�롣ʧ��ʱ����NULL��
264 static struct m_inode * get_dir(const char * pathname, struct m_inode * inode)
265 {
266 char c;
267 const char * thisname;
268 struct buffer_head * bh;
269 int namelen,inr;
270 struct dir_entry * de;
271 struct m_inode * dir;
272
// �����жϲ�����Ч�ԡ����������ָ��Ŀ¼��i�ڵ�ָ��inodeΪ�գ���ʹ�õ�ǰ���̵ĵ�
// ǰ����Ŀ¼i�ڵ㡣����û�ָ��·�����ĵ�1���ַ���'/'����˵��·�����Ǿ���·������
// ��Ӧ�ôӵ�ǰ��������ṹ�����õĸ�����α����i�ڵ㿪ʼ����������������Ҫ�ȷŻز�
// ��ָ���Ļ����趨��Ŀ¼i�ڵ㣬��ȡ�ý���ʹ�õĸ�i�ڵ㡣Ȼ��Ѹ�i�ڵ�����ü���
// ��1����ɾ��·�����ĵ�1���ַ� '/'�������Ϳ��Ա�֤��ǰ����ֻ�������趨�ĸ�i�ڵ�
// ��Ϊ��������㡣
273 if (!inode) {
274 inode = current->pwd; // ���̵ĵ�ǰ����Ŀ¼i�ڵ㡣
275 inode->i_count++;
276 }
277 if ((c=get_fs_byte(pathname))=='/') {
278 iput(inode); // �Ż�ԭi�ڵ㡣
279 inode = current->root; // Ϊ����ָ���ĸ�i�ڵ㡣
280 pathname++;
281 inode->i_count++;
282 }
// Ȼ�����·�����еĸ���Ŀ¼�����ֺ��ļ�������ѭ����������ѭ�����������У�������Ҫ
// �Ե�ǰ���ڴ�����Ŀ¼�����ֵ� i�ڵ������Ч���жϣ����Ұѱ���thisname ָ��ǰ��
// �ڴ�����Ŀ¼�����֡������i�ڵ������ǰ������Ŀ¼�����ֲ���Ŀ¼���ͣ�����û�п�
// �����Ŀ¼�ķ������ɣ���Żظ�i�ڵ㣬������NULL�˳��� ��Ȼ�ڸս���ѭ��ʱ����ǰ
// Ŀ¼��i�ڵ�inode���ǽ��̸�i�ڵ�����ǵ�ǰ����Ŀ¼��i�ڵ㣬�����Dz���ָ����ij
// ��������ʼĿ¼��i�ڵ㡣
283 while (1) {
284 thisname = pathname;
285 if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
286 iput(inode);
287 return NULL;
288 }
// ÿ��ѭ�����Ǵ���·������һ��Ŀ¼�������ļ��������֡������ÿ��ѭ�������Ƕ�Ҫ��·
// �����ַ����з����һ��Ŀ¼�������ļ������������Ǵӵ�ǰ·����ָ�� pathname ��ʼ��
// ��������ַ���ֱ���ַ���һ����β����NULL��������һ��'/'�ַ�����ʱ���� namelen ��
// ���ǵ�ǰ����Ŀ¼�����ֵij��ȣ������� thisname ��ָ���Ŀ¼�����ֵĿ�ʼ������ʱ��
// ���ַ��ǽ�β��NULL��������Ѿ�������·����ĩβ�����ѵ������ָ��Ŀ¼�����ļ�����
// �ظ�i�ڵ�ָ���˳���
// ע�⣡���·���������һ������Ҳ��һ��Ŀ¼�����������û�м��� '/'�ַ���������
// �᷵�ظ����Ŀ¼����i�ڵ㣡���磺����·����/usr/src/linux���ú�����ֻ����src/Ŀ
// ¼����i�ڵ㡣
289 for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
290 /* nothing */ ;
291 if (!c)
292 return inode;
// �ڵõ���ǰĿ¼�����֣����ļ����������ǵ��ò���Ŀ¼���find_entry()�ڵ�ǰ��
// ����Ŀ¼��Ѱ��ָ�����Ƶ�Ŀ¼����û���ҵ�����Żظ�i�ڵ㣬������NULL�˳���
// Ȼ�����ҵ���Ŀ¼����ȡ����i�ڵ��inr���豸��idev���ͷŰ�����Ŀ¼��ĸ��ٻ���
// �鲢�Żظ�i�ڵ㡣 Ȼ��ȡ�ڵ��inr��i�ڵ�inode�����Ը�Ŀ¼��Ϊ��ǰĿ¼����ѭ
// ������·�����е���һĿ¼�����֣����ļ������������ǰ������Ŀ¼����һ����������
// ������ʹ��follow_link()�Ϳ��Եõ���ָ���Ŀ¼������i�ڵ㡣
293 if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
294 iput(inode);
295 return NULL;
296 }
297 inr = de->inode; // ��ǰĿ¼�����ֵ�i�ڵ�š�
298 brelse(bh);
299 dir = inode;
300 if (!(inode = iget(dir->i_dev,inr))) { // ȡi�ڵ����ݡ�
301 iput(dir);
302 return NULL;
303 }
304 if (!(inode = follow_link(dir,inode)))
305 return NULL;
306 }
307 }
308
309 /*
310 * dir_namei()
311 *
312 * dir_namei() returns the inode of the directory of the
313 * specified name, and the name within that directory.
314 */
/*
* dir_namei()
*
* dir_namei()��������ָ��Ŀ¼����i�ڵ�ָ�룬�Լ������
* Ŀ¼�����ơ�
*/
// ������pathname - Ŀ¼·������namelen - ·�������ȣ�name - ���ص����Ŀ¼����
// base - ������ʼĿ¼��i�ڵ㡣
// ���أ�ָ��Ŀ¼�����Ŀ¼��i�ڵ�ָ������Ŀ¼���Ƽ����ȡ�����ʱ����NULL��
// ע�⣡��������Ŀ¼����ָ·���������ĩ�˵�Ŀ¼��
315 static struct m_inode * dir_namei(const char * pathname,
316 int * namelen, const char ** name, struct m_inode * base)
317 {
318 char c;
319 const char * basename;
320 struct m_inode * dir;
321
// ����ȡ��ָ��·�������Ŀ¼��i�ڵ㡣Ȼ���·����pathname����������⣬������
// һ��'/'�ַ�����������ַ����������䳤�ȣ����ҷ������Ŀ¼��i�ڵ�ָ�롣ע�⣡��
// ��·�������һ���ַ���б���ַ�'/'����ô���ص�Ŀ¼��Ϊ�գ����ҳ���Ϊ0�������ص�i
// �ڵ�ָ����Ȼָ�����һ��'/'�ַ�ǰĿ¼����i�ڵ㡣�μ���289���ϵġ�ע�⡱˵����
322 if (!(dir = get_dir(pathname,base))) // base��ָ������ʼĿ¼i�ڵ㡣
323 return NULL;
324 basename = pathname;
325 while (c=get_fs_byte(pathname++))
326 if (c=='/')
327 basename=pathname;
328 *namelen = pathname-basename-1;
329 *name = basename;
330 return dir;
331 }
332
//// ȡָ��·������i�ڵ��ڲ�������
// ������pathname - ·������base - �������Ŀ¼i�ڵ㣻follow_links - �Ƿ����
// �������ӵı�־��1 - ��Ҫ��0����Ҫ��
// ���أ���Ӧ��i�ڵ㡣
333 struct m_inode * _namei(const char * pathname, struct m_inode * base,
334 int follow_links)
335 {
336 const char * basename;
337 int inr,namelen;
338 struct m_inode * inode;
339 struct buffer_head * bh;
340 struct dir_entry * de;
341
// ���Ȳ���ָ��·���������Ŀ¼��Ŀ¼�����õ���i�ڵ㡣�������ڣ���NULL�˳���
// ������ص�������ֵij�����0�����ʾ��·������һ��Ŀ¼��Ϊ���һ����˵����
// ���Ѿ��ҵ���ӦĿ¼��i�ڵ㣬����ֱ�ӷ��ظ�i�ڵ��˳���������ص����ֳ��Ȳ���0��
// ��������ָ������ʼĿ¼base���ٴε���dir_namei()��������������Ŀ¼���������ݷ���
// ����Ϣ�������жϡ�
311 if (!(dir = dir_namei(pathname,&namelen,&basename)))
312 return NULL;
313 if (!namelen) /* special case: '/usr/' etc */
314 return dir; /* ��Ӧ��'/usr/'����� */
342 if (!(base = dir_namei(pathname,&namelen,&basename,base)))
343 return NULL;
344 if (!namelen) /* special case: '/usr/' etc */
345 return base;
// Ȼ���ڷ��صĶ���Ŀ¼��Ѱ��ָ���ļ���Ŀ¼���i�ڵ㡣ע�⣡��Ϊ������Ҳ��һ��Ŀ
// ¼���������û�м�'/'���᷵�ظ����Ŀ¼��i�ڵ㣡 ���磺/usr/src/linux����ֻ
// ���� src/Ŀ¼����i�ڵ㡣��Ϊ����dir_namei() ������'/'���������һ�����ֵ���һ��
// �ļ��������������������Ҫ�������������ʹ��Ѱ��Ŀ¼��i�ڵ㺯��find_entry()����
// ��������ʱde�к���Ѱ�ҵ���Ŀ¼��ָ�룬��dir�ǰ�����Ŀ¼���Ŀ¼��i�ڵ�ָ�롣
346 bh = find_entry(&base,basename,namelen,&de);
347 if (!bh) {
348 iput(base);
349 return NULL;
350 }
// ����ȡ��Ŀ¼���i�ڵ�ţ����ͷŰ�����Ŀ¼��ĸ��ٻ���鲢�Ż�Ŀ¼i�ڵ㡣Ȼ��ȡ
// ��Ӧ�ڵ�ŵ�i�ڵ㣬���䱻����ʱ��Ϊ��ǰʱ�䣬�������ı�־����ظ�i�ڵ�
// ָ��inode�������ǰ������Ŀ¼����һ����������������ʹ��follow_link()�õ���ָ���
// Ŀ¼������i�ڵ㡣
351 inr = de->inode;
352 brelse(bh);
353 if (!(inode = iget(base->i_dev,inr))) {
354 iput(base);
355 return NULL;
356 }
357 if (follow_links)
358 inode = follow_link(base,inode);
359 else
360 iput(base);
361 inode->i_atime=CURRENT_TIME;
362 inode->i_dirt=1;
363 return inode;
364 }
365
//// ȡָ��·������i�ڵ㣬������������ӡ�
// ������pathname - ·������
// ���أ���Ӧ��i�ڵ㡣
366 struct m_inode * lnamei(const char * pathname)
367 {
368 return _namei(pathname, NULL, 0);
369 }
370
371 /*
372 * namei()
373 *
374 * is used by most simple commands to get the inode of a specified name.
375 * Open, link etc use their own routines, but this is enough for things
376 * like 'chmod' etc.
377 */
/*
* namei()
*
* �ú������������������ȡ��ָ��·�����Ƶ�i�ڵ㡣open��link����ʹ������
* �Լ�����Ӧ����������������ģʽ'chmod'������������ú������㹻���ˡ�
*/
//// ȡָ��·������i�ڵ㣬����������ӡ�
// ������pathname - ·������
// ���أ���Ӧ��i�ڵ㡣
378 struct m_inode * namei(const char * pathname)
379 {
380 return _namei(pathname,NULL,1);
381 }
382
383 /*
384 * open_namei()
385 *
386 * namei for open - this is in fact almost the whole open-routine.
387 */
/*
* open_namei()
*
* open()����ʹ�õ�namei���� - ����ʵ�����������Ĵ��ļ�����
*/
//// ���namei������
// ����filename���ļ�·������flag�Ǵ��ļ���־����ȡֵO_RDONLY��ֻ������O_WRONLY
// ��ֻд����O_RDWR����д�����Լ�O_CREAT����������O_EXCL���������ļ����벻���ڣ���
// O_APPEND�����ļ�β�������ݣ�������һЩ��־����ϡ���������ô�����һ�����ļ�����
// mode������ָ���ļ����������ԡ���Щ������S_IRWXU���ļ��������ж���д��ִ��Ȩ�ޣ���
// S_IRUSR���û����ж��ļ�Ȩ�ޣ���S_IRWXG�����Ա���ж���д��ִ��Ȩ�ޣ��ȵȡ�������
// �������ļ�����Щ����ֻӦ���ڽ������ļ��ķ��ʣ�������ֻ���ļ��Ĵ���Ҳ������һ
// ���ɶ�д���ļ�������μ������ļ�sys/stat.h��fcntl.h��
// ���أ��ɹ�����0�����س����룻res_inode - ���ض�Ӧ�ļ�·������i�ڵ�ָ�롣
388 int open_namei(const char * pathname, int flag, int mode,
389 struct m_inode ** res_inode)
390 {
391 const char * basename;
392 int inr,dev,namelen;
393 struct m_inode * dir, *inode;
394 struct buffer_head * bh;
395 struct dir_entry * de;
396
// ���ȶԺ����������к����Ĵ���������ļ�����ģʽ��־��ֻ����0���������ļ������־
// O_TRUNCȴ��λ�ˣ������ļ���־������ֻд��־O_WRONLY����������ԭ�������ڽ���
// ��־O_TRUNC�������ļ���д����²���Ч��Ȼ��ʹ�õ�ǰ���̵��ļ��������������룬��
// �ε�����ģʽ�е���Ӧλ����������ͨ�ļ���־I_REGULAR���ñ�־�����ڴ��ļ�����
// �ڶ���Ҫ�����ļ�ʱ����Ϊ���ļ���Ĭ�����ԡ��μ�����411���ϵ�ע�͡�
397 if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
398 flag |= O_WRONLY;
399 mode &= 0777 & ~current->umask;
400 mode |= I_REGULAR; // �����ļ���־�����μ�include/const.h�ļ�����
// Ȼ�����ָ����·����Ѱ�ҵ���Ӧ��i�ڵ㣬�Լ����Ŀ¼�����䳤�ȡ���ʱ������
// Ŀ¼������Ϊ0�� ����'/usr/' ����·���������������ô���������Ƕ�д���������ļ���
// �Ƚ�0�����ʾ���ڴ�һ��Ŀ¼���ļ�����������ֱ�ӷ��ظ�Ŀ¼��i�ڵ㲢����0�˳���
// ����˵�����̲����Ƿ������ǷŻظ�i�ڵ㣬���س����롣
401 if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
402 return -ENOENT;
403 if (!namelen) { /* special case: '/usr/' etc */
404 if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
405 *res_inode=dir;
406 return 0;
407 }
408 iput(dir);
409 return -EISDIR;
410 }
// ���Ÿ�������õ������Ŀ¼����i�ڵ�dir�������в���ȡ��·�����ַ�����������
// ������Ӧ��Ŀ¼��ṹde����ͬʱ�õ���Ŀ¼�����ڵĸ��ٻ�����ָ�롣 ����ø��ٻ���
// ָ��ΪNULL�����ʾû���ҵ���Ӧ�ļ�����Ŀ¼����ֻ�����Ǵ����ļ������� ��ʱ��
// �����Ǵ����ļ�����Żظ�Ŀ¼��i�ڵ㣬���س������˳�������û��ڸ�Ŀ¼û��д��Ȩ
// ������Żظ�Ŀ¼��i�ڵ㣬���س������˳���
411 bh = find_entry(&dir,basename,namelen,&de);
412 if (!bh) {
413 if (!(flag & O_CREAT)) {
414 iput(dir);
415 return -ENOENT;
416 }
417 if (!permission(dir,MAY_WRITE)) {
418 iput(dir);
419 return -EACCES;
420 }
// ��������ȷ�����Ǵ�������������д�������ɡ� ������Ǿ���Ŀ¼i�ڵ��Ӧ�豸������
// һ���µ�i�ڵ��·������ָ�����ļ�ʹ�á� ��ʧ����Ż�Ŀ¼��i�ڵ㣬������û�п�
// ������롣����ʹ�ø��� i�ڵ㣬������г�ʼ���ã��ýڵ���û�id����Ӧ�ڵ����ģ
// ʽ�������ı�־��Ȼ����ָ��Ŀ¼dir������һ����Ŀ¼�
421 inode = new_inode(dir->i_dev);
422 if (!inode) {
423 iput(dir);
424 return -ENOSPC;
425 }
426 inode->i_uid = current->euid;
427 inode->i_mode = mode;
428 inode->i_dirt = 1;
429 bh = add_entry(dir,basename,namelen,&de);
// ������ص�Ӧ�ú�����Ŀ¼��ĸ��ٻ�����ָ��ΪNULL�����ʾ����Ŀ¼�����ʧ�ܡ�����
// ������i�ڵ���������Ӽ�����1���Żظ�i�ڵ���Ŀ¼��i�ڵ㲢���س������˳��� ����
// ˵������Ŀ¼������ɹ��� �������������ø���Ŀ¼���һЩ��ʼֵ����i�ڵ��Ϊ������
// ����i�ڵ�ĺ��룻���ø��ٻ��������ı�־�� Ȼ���ͷŸø��ٻ��������Ż�Ŀ¼��i��
// �㡣������Ŀ¼���i�ڵ�ָ�룬���ɹ��˳���
430 if (!bh) {
431 inode->i_nlinks--;
432 iput(inode);
433 iput(dir);
434 return -ENOSPC;
435 }
436 de->inode = inode->i_num;
437 bh->b_dirt = 1;
438 brelse(bh);
439 iput(dir);
440 *res_inode = inode;
441 return 0;
442 }
// �����棨411�У���Ŀ¼��ȡ�ļ�����ӦĿ¼��ṹ�IJ����ɹ�����bh��ΪNULL������˵
// ��ָ�����ļ��Ѿ����ڡ�����ȡ����Ŀ¼���i�ڵ�ź��������豸�ţ����ͷŸø���
// �������Լ��Ż�Ŀ¼��i�ڵ㡣�����ʱ��ռ������־O_EXCL��λ���������ļ��Ѿ����ڣ�
// ���ļ��Ѵ��ڳ������˳���
443 inr = de->inode;
444 dev = dir->i_dev;
445 brelse(bh);
446 if (flag & O_EXCL) {
447 iput(dir);
448 return -EEXIST;
449 }
// Ȼ�����Ƕ�ȡ��Ŀ¼���i�ڵ����ݡ�����i�ڵ���һ��Ŀ¼��i�ڵ㲢�ҷ���ģʽ��ֻ
// д���д������û�з��ʵ�����Ȩ�ޣ���Żظ�i�ڵ㣬���ط���Ȩ�������˳���
450 if (!(inode = follow_link(dir,iget(dev,inr))))
451 return -EACCES;
452 if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
453 !permission(inode,ACC_MODE(flag))) {
454 iput(inode);
455 return -EPERM;
456 }
// �������Ǹ��¸�i�ڵ�ķ���ʱ���ֶ�ֵΪ��ǰʱ�䡣��������˽�0��־����i��
// ����ļ����Ƚ�Ϊ0����ظ�Ŀ¼��i�ڵ��ָ�룬������0���ɹ�����
457 inode->i_atime = CURRENT_TIME;
458 if (flag & O_TRUNC)
459 truncate(inode);
460 *res_inode = inode;
461 return 0;
462 }
463
//// ����һ���豸�����ļ�����ͨ�ļ��ڵ㣨node����
// �ú�����������Ϊfilename����mode��devָ�����ļ�ϵͳ�ڵ㣨��ͨ�ļ����豸������
// ���������ܵ�����
// ������filename - ·������mode - ָ��ʹ�������Լ��������ڵ�����ͣ�dev - �豸�š�
// ���أ��ɹ���0�����س����롣
464 int sys_mknod(const char * filename, int mode, int dev)
465 {
466 const char * basename;
467 int namelen;
468 struct m_inode * dir, * inode;
469 struct buffer_head * bh;
470 struct dir_entry * de;
471
// ���ȼ��������ɺͲ�������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣������dz����û�����
// ���ط������ɳ����롣����Ҳ�����Ӧ·�����ж���Ŀ¼��i�ڵ㣬�س����롣�����
// ���˵��ļ�������Ϊ0����˵��������·�������û��ָ���ļ������Żظ�Ŀ¼i�ڵ㣬��
// �س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�Ŀ¼��i�ڵ㣬���ط������ɳ���
// ���˳���������dz����û����ط������ɳ����롣
472 if (!suser())
473 return -EPERM;
474 if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
475 return -ENOENT;
476 if (!namelen) {
477 iput(dir);
478 return -ENOENT;
479 }
480 if (!permission(dir,MAY_WRITE)) {
481 iput(dir);
482 return -EPERM;
483 }
// Ȼ����������һ��·����ָ�����ļ��Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ���ļ��ڵ㡣
// �����Ӧ·�����������ļ�����Ŀ¼���Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������鲢�Ż�
// Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳���
484 bh = find_entry(&dir,basename,namelen,&de);
485 if (bh) {
486 brelse(bh);
487 iput(dir);
488 return -EEXIST;
489 }
// �������Ǿ�����һ���µ�i�ڵ㣬�����ø�i�ڵ������ģʽ�����Ҫ�������ǿ��豸�ļ�
// �������ַ��豸�ļ�������i�ڵ��ֱ������ָ��0�����豸�š��������豸�ļ���˵��
// ��i�ڵ��i_zone[0]�д�ŵ��Ǹ��豸�ļ��������豸���豸�š�Ȼ�����ø�i�ڵ����
// ��ʱ�䡢����ʱ��Ϊ��ǰʱ�䣬������i�ڵ����ı�־��
490 inode = new_inode(dir->i_dev);
491 if (!inode) { // �����ɹ���Ż�Ŀ¼i�ڵ㣬�����ռ�������˳���
492 iput(dir);
493 return -ENOSPC;
494 }
495 inode->i_mode = mode;
496 if (S_ISBLK(mode) || S_ISCHR(mode))
497 inode->i_zone[0] = dev;
498 inode->i_mtime = inode->i_atime = CURRENT_TIME;
499 inode->i_dirt = 1;
// ����Ϊ����µ�i�ڵ���Ŀ¼��������һ��Ŀ¼����ʧ�ܣ�������Ŀ¼��ĸ��ٻ���
// ��ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻���������i�ڵ��������Ӽ�����λ�����Żظ�
// i�ڵ㣬���س������˳���
500 bh = add_entry(dir,basename,namelen,&de);
501 if (!bh) {
502 iput(dir);
503 inode->i_nlinks=0;
504 iput(inode);
505 return -ENOSPC;
506 }
// ��������Ŀ¼�����Ҳ�ɹ��ˣ������������������Ŀ¼�����ݡ����Ŀ¼���i�ڵ���
// �ε�����i�ڵ�ţ����ø��ٻ��������ı�־���Ż�Ŀ¼���µ�i�ڵ㣬�ͷŸ��ٻ���
// �������0(�ɹ�)��
507 de->inode = inode->i_num;
508 bh->b_dirt = 1;
509 iput(dir);
510 iput(inode);
511 brelse(bh);
512 return 0;
513 }
514
//// ����һ��Ŀ¼��
// ������pathname - ·������mode - Ŀ¼ʹ�õ�Ȩ�����ԡ�
// ���أ��ɹ���0�����س����롣
515 int sys_mkdir(const char * pathname, int mode)
516 {
517 const char * basename;
518 int namelen;
519 struct m_inode * dir, * inode;
520 struct buffer_head * bh, *dir_block;
521 struct dir_entry * de;
522
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// ��i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳���������dz����û����ط������ɳ����롣
523 if (!(dir = dir_namei(pathname,&namelen,&basename, NULL)))
524 return -ENOENT;
525 if (!namelen) {
526 iput(dir);
527 return -ENOENT;
528 }
529 if (!permission(dir,MAY_WRITE)) {
530 iput(dir);
531 return -EPERM;
532 }
// Ȼ����������һ��·����ָ����Ŀ¼���Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ��Ŀ¼�ڵ㡣
// �����Ӧ·����������Ŀ¼����Ŀ¼���Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������鲢�Ż�
// Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳����������Ǿ�����һ���µ�i�ڵ㣬������
// ��i�ڵ������ģʽ���ø���i�ڵ��Ӧ���ļ�����Ϊ32�ֽ� ��2��Ŀ¼��Ĵ�С������
// �ڵ����ı�־���Լ��ڵ����ʱ��ͷ���ʱ�䡣2��Ŀ¼��ֱ�����'.'��'..'Ŀ¼��
533 bh = find_entry(&dir,basename,namelen,&de);
534 if (bh) {
535 brelse(bh);
536 iput(dir);
537 return -EEXIST;
538 }
539 inode = new_inode(dir->i_dev);
540 if (!inode) { // �����ɹ���Ż�Ŀ¼��i�ڵ㣬�����ռ�����롣
541 iput(dir);
542 return -ENOSPC;
543 }
544 inode->i_size = 32;
545 inode->i_dirt = 1;
546 inode->i_mtime = inode->i_atime = CURRENT_TIME;
// ����Ϊ����i�ڵ�����һ���ڱ���Ŀ¼�����ݵĴ��̿飬����i�ڵ�ĵ�һ��ֱ�ӿ�ָ���
// �ڸÿ�š��������ʧ����Żض�ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ�
// �µ�i�ڵ㣬����û�пռ�������˳��������ø��µ�i�ڵ����ı�־��
547 if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
548 iput(dir);
549 inode->i_nlinks--;
550 iput(inode);
551 return -ENOSPC;
552 }
553 inode->i_dirt = 1;
// ���豸�϶�ȡ������Ĵ��̿飨Ŀ���ǰѶ�Ӧ��ŵ����ٻ������У�������������Żض�Ӧ
// Ŀ¼��i�ڵ㣻�ͷ�����Ĵ��̿飻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬��
// ��û�пռ�������˳���
554 if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
555 iput(dir);
556 inode->i_nlinks--;
557 iput(inode);
558 return -ERROR;
559 }
// Ȼ�������ڻ�����н�����������Ŀ¼�ļ��е�2��Ĭ�ϵ���Ŀ¼�'.'��'..'���ṹ��
// �ݡ�������deָ����Ŀ¼������ݿ飬Ȼ���ø�Ŀ¼���i�ڵ���ֶε����������i
// �ڵ�ţ������ֶε���"."�� Ȼ��deָ����һ��Ŀ¼��ṹ�����ڸýṹ�д���ϼ�Ŀ¼
// �� i�ڵ�ź�����".."��Ȼ�����øø��ٻ�������ı�־�����ͷŸû���顣�ٳ�ʼ��
// ������i�ڵ��ģʽ�ֶΣ����ø�i�ڵ����ı�־��
560 de = (struct dir_entry *) dir_block->b_data;
561 de->inode=inode->i_num; // ����'.'Ŀ¼�
562 strcpy(de->name,".");
563 de++;
564 de->inode = dir->i_num; // ����'..'Ŀ¼�
565 strcpy(de->name,"..");
566 inode->i_nlinks = 2;
567 dir_block->b_dirt = 1;
568 brelse(dir_block);
569 inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
570 inode->i_dirt = 1;
// ����������ָ��Ŀ¼��������һ��Ŀ¼����ڴ���½�Ŀ¼��i�ڵ��Ŀ¼�������ʧ
// �ܣ�������Ŀ¼��ĸ��ٻ�����ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻�������i�ڵ���
// �����Ӽ�����λ�����Żظ�i�ڵ㡣���س������˳���
571 bh = add_entry(dir,basename,namelen,&de);
572 if (!bh) {
573 iput(dir);
574 inode->i_nlinks=0;
575 iput(inode);
576 return -ENOSPC;
577 }
// ��������Ŀ¼���i�ڵ��ֶε�����i�ڵ�ţ����ø��ٻ�������ı�־���Ż�Ŀ¼
// ���µ�i�ڵ㣬�ͷŸ��ٻ����������0���ɹ�����
578 de->inode = inode->i_num;
579 bh->b_dirt = 1;
580 dir->i_nlinks++;
581 dir->i_dirt = 1;
582 iput(dir);
583 iput(inode);
584 brelse(bh);
585 return 0;
586 }
587
588 /*
589 * routine to check that the specified directory is empty (for rmdir)
590 */
/*
* ���ڼ��ָ����Ŀ¼�Ƿ�Ϊ�յ��ӳ�������rmdirϵͳ���ã���
*/
//// ���ָ��Ŀ¼�Ƿ�ա�
// ������inode - ָ��Ŀ¼��i�ڵ�ָ�롣
// ���أ�1 �C Ŀ¼���ǿյģ�0 - ���ա�
591 static int empty_dir(struct m_inode * inode)
592 {
593 int nr,block;
594 int len;
595 struct buffer_head * bh;
596 struct dir_entry * de;
597
// ���ȼ���ָ��Ŀ¼������Ŀ¼���������鿪ʼ�����ض�Ŀ¼������Ϣ�Ƿ���ȷ��һ��Ŀ¼
// ��Ӧ��������2��Ŀ¼���"."��".."�� ���Ŀ¼���������2�����߸�Ŀ¼i�ڵ�ĵ�
// 1��ֱ�ӿ�û��ָ���κδ��̿�ţ����߸�ֱ�ӿ������������ʾ������Ϣ���豸dev ��Ŀ
// ¼����������0(ʧ��)��
598 len = inode->i_size / sizeof (struct dir_entry); // Ŀ¼��Ŀ¼�������
599 if (len<2 || !inode->i_zone[0] ||
600 !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
601 printk("warning - bad directory on dev %04x\n",inode->i_dev);
602 return 0;
603 }
// ��ʱbh��ָ������к���Ŀ¼�����ݡ�������Ŀ¼��ָ��deָ����е�1��Ŀ¼�
// ���ڵ�1��Ŀ¼�"."��������i�ڵ���ֶ�inodeӦ�õ��ڵ�ǰĿ¼��i�ڵ�š�����
// ��2��Ŀ¼�".."��������i�ڵ���ֶ� inode Ӧ�õ�����һ��Ŀ¼��i�ڵ�ţ�����
// Ϊ0����������1��Ŀ¼���i�ڵ���ֶ�ֵ�����ڸ�Ŀ¼��i�ڵ�ţ����ߵ�2��Ŀ¼
// ���i�ڵ���ֶ�Ϊ�㣬��������Ŀ¼��������ֶβ��ֱ����"."��".."������ʾ������
// ����Ϣ���豸dev��Ŀ¼������������0��
604 de = (struct dir_entry *) bh->b_data;
605 if (de[0].inode != inode->i_num || !de[1].inode ||
606 strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
607 printk("warning - bad directory on dev %04x\n",inode->i_dev);
608 return 0;
609 }
// Ȼ��������nr����Ŀ¼����ţ���0��ʼ�ƣ���deָ�������Ŀ¼���ѭ������Ŀ¼
// ���������еģ�len - 2����Ŀ¼�����û��Ŀ¼���i�ڵ���ֶβ�Ϊ0����ʹ�ã���
610 nr = 2;
611 de += 2;
612 while (nr<len) {
// ����ÿ���̿��е�Ŀ¼���Ѿ�ȫ�������ϣ����ͷŸô��̿�Ļ���飬����ȡĿ¼����
// �ļ�����һ�麬��Ŀ¼��Ĵ��̿顣��ȡ�ķ����Ǹ��ݵ�ǰ����Ŀ¼����� nr �������
// ӦĿ¼����Ŀ¼�����ļ��е����ݿ�ţ�nr/DIR_ENTRIES_PER_BLOCK����Ȼ��ʹ�� bmap()
// ����ȡ�ö�Ӧ���̿�� block����ʹ�ö��豸�̿麯��bread() ����Ӧ�̿���뻺����У�
// �����ظû�����ָ�롣������ȡ����Ӧ�̿�û��ʹ�ã����Ѿ����ã����ļ��Ѿ�ɾ���ȣ���
// ���������һ�飬�������������������0��������deָ����������Ŀ¼�
613 if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
614 brelse(bh);
615 block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
616 if (!block) {
617 nr += DIR_ENTRIES_PER_BLOCK;
618 continue;
619 }
620 if (!(bh=bread(inode->i_dev,block)))
621 return 0;
622 de = (struct dir_entry *) bh->b_data;
623 }
// ����deָ��ĵ�ǰĿ¼������Ŀ¼���i�ڵ���ֶβ�����0�����ʾ��Ŀ¼��Ŀǰ��
// ��ʹ�ã����ͷŸø��ٻ�����������0�˳�����������û�в�ѯ���Ŀ¼�е�����Ŀ¼�
// ���Ŀ¼�����nr��1��deָ����һ��Ŀ¼�������⡣
624 if (de->inode) {
625 brelse(bh);
626 return 0;
627 }
628 de++;
629 nr++;
630 }
// ִ�е�����˵����Ŀ¼��û���ҵ����õ�Ŀ¼��(��Ȼ����ͷ��������)�����ͷŻ���鷵��1��
631 brelse(bh);
632 return 1;
633 }
//// ɾ��Ŀ¼��
// ������ name - Ŀ¼����·��������
// ���أ�����0��ʾ�ɹ������س����š�
635 int sys_rmdir(const char * name)
636 {
637 const char * basename;
638 int namelen;
639 struct m_inode * dir, * inode;
640 struct buffer_head * bh;
641 struct dir_entry * de;
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// ��i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳���������dz����û����ط������ɳ����롣
643 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
644 return -ENOENT;
645 if (!namelen) {
646 iput(dir);
647 return -ENOENT;
648 }
649 if (!permission(dir,MAY_WRITE)) {
650 iput(dir);
651 return -EPERM;
652 }
// Ȼ�����ָ��Ŀ¼��i�ڵ��Ŀ¼�����ú���find_entry()Ѱ�Ҷ�ӦĿ¼������ذ�����
// Ŀ¼��Ļ����ָ��bh��������Ŀ¼���Ŀ¼��i�ڵ�ָ��dir��Ŀ¼��ָ��de���ٸ���
// ��Ŀ¼��de �е�i�ڵ������ iget()�����õ���Ӧ��i�ڵ� inode�������Ӧ·��������
// ��Ŀ¼����Ŀ¼����ڣ����ͷŰ�����Ŀ¼��ĸ��ٻ��������Ż�Ŀ¼�� i�ڵ㣬������
// ���Ѿ����ڳ����룬���˳������ȡĿ¼���i�ڵ��������Ż�Ŀ¼�� i�ڵ㣬���ͷź�
// ��Ŀ¼��ĸ��ٻ����������س����š�
653 bh = find_entry(&dir,basename,namelen,&de);
654 if (!bh) {
655 iput(dir);
656 return -ENOENT;
657 }
658 if (!(inode = iget(dir->i_dev, de->inode))) {
659 iput(dir);
660 brelse(bh);
661 return -EPERM;
662 }
// ��ʱ�������а���Ҫ��ɾ��Ŀ¼���Ŀ¼i�ڵ�dir��Ҫ��ɾ��Ŀ¼���i�ڵ�inode��Ҫ
// ��ɾ��Ŀ¼��ָ��de����������ͨ������3����������Ϣ�ļ������֤ɾ�������Ŀ����ԡ�
// ����Ŀ¼����������ɾ����־���ҽ��̵���Ч�û�id��euid������root�����ҽ��̵���Ч
// �û�id��euid�������ڸ�i�ڵ���û�id�����ʾ��ǰ����û��Ȩ��ɾ����Ŀ¼�����Ƿ�
// �ذ���Ҫɾ��Ŀ¼����Ŀ¼ i�ڵ��Ҫɾ��Ŀ¼�� i�ڵ㣬Ȼ���ͷŸ��ٻ�����������
// �����롣
663 if ((dir->i_mode & S_ISVTX) && current->euid &&
664 inode->i_uid != current->euid) {
665 iput(dir);
666 iput(inode);
667 brelse(bh);
668 return -EPERM;
669 }
// ���Ҫ��ɾ����Ŀ¼��i�ڵ���豸�Ų����ڰ�����Ŀ¼���Ŀ¼���豸�ţ����߸ñ�ɾ��
// Ŀ¼���������Ӽ������� 1����ʾ�з������ӵȣ�������ɾ����Ŀ¼�������ͷŰ���Ҫɾ
// ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
670 if (inode->i_dev != dir->i_dev || inode->i_count>1) {
671 iput(dir);
672 iput(inode);
673 brelse(bh);
674 return -EPERM;
675 }
// ���Ҫ��ɾ��Ŀ¼��Ŀ¼��i�ڵ�͵��ڰ�������ɾ��Ŀ¼��Ŀ¼i�ڵ㣬���ʾ��ͼɾ��
// "."Ŀ¼�����Dz������ġ����ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬
// �ͷŸ��ٻ���飬���س����롣
676 if (inode == dir) { /* we may not delete ".", but "../dir" is ok */
677 iput(inode);
678 iput(dir);
679 brelse(bh);
680 return -EPERM;
681 }
// ��Ҫ��ɾ��Ŀ¼i�ڵ�����Ա����ⲻ��һ��Ŀ¼����ɾ��������ǰ����ȫ�����ڡ�����
// �Żذ���ɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
682 if (!S_ISDIR(inode->i_mode)) {
683 iput(inode);
684 iput(dir);
685 brelse(bh);
686 return -ENOTDIR;
687 }
// �����豻ɾ����Ŀ¼���գ���Ҳ����ɾ�������ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫ
// ɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
688 if (!empty_dir(inode)) {
689 iput(inode);
690 iput(dir);
691 brelse(bh);
692 return -ENOTEMPTY;
693 }
// ����һ����Ŀ¼����Ŀ¼��������Ӧ��Ϊ2�����ӵ��ϲ�Ŀ¼�ͱ�Ŀ¼���������豻ɾ��Ŀ
// ¼��i�ڵ��������������2������ʾ������Ϣ����ɾ��������Ȼ����ִ�С������ø��豻
// ɾ��Ŀ¼��Ŀ¼���i�ڵ���ֶ�Ϊ0����ʾ��Ŀ¼���ʹ�ã����ú��и�Ŀ¼��ĸ���
// ��������ı�־�����ͷŸû���顣Ȼ�����ñ�ɾ��Ŀ¼i�ڵ��������Ϊ0����ʾ���У���
// ����i�ڵ����ı�־��
694 if (inode->i_nlinks != 2)
695 printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
696 de->inode = 0;
697 bh->b_dirt = 1;
698 brelse(bh);
699 inode->i_nlinks=0;
700 inode->i_dirt=1;
// �ٽ�������ɾ��Ŀ¼����Ŀ¼��i�ڵ����Ӽ�����1������ı�ʱ�����ʱ��Ϊ��ǰʱ
// �䣬���øýڵ����ı�־�����Żذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i
// �ڵ㣬����0��ɾ�������ɹ�����
701 dir->i_nlinks--;
702 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
703 dir->i_dirt=1;
704 iput(dir);
705 iput(inode);
706 return 0;
707 }
//// ɾ�����ͷţ��ļ�����Ӧ��Ŀ¼�
// ���ļ�ϵͳɾ��һ�����֡�������ļ������һ�����ӣ�����û�н��������ļ������
// �ļ�Ҳ����ɾ�������ͷ���ռ�õ��豸�ռ䡣
// ������name - �ļ�����·��������
// ���أ��ɹ���0�����س����š�
709 int sys_unlink(const char * name)
710 {
711 const char * basename;
712 int namelen;
713 struct m_inode * dir, * inode;
714 struct buffer_head * bh;
715 struct dir_entry * de;
716
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// �� i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳�������Ҳ�����Ӧ·��������Ŀ¼��i�ڵ㣬��
// �س����롣
717 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
718 return -ENOENT;
719 if (!namelen) {
720 iput(dir);
721 return -ENOENT;
722 }
723 if (!permission(dir,MAY_WRITE)) {
724 iput(dir);
725 return -EPERM;
726 }
// Ȼ�����ָ��Ŀ¼��i�ڵ��Ŀ¼�����ú���find_entry()Ѱ�Ҷ�ӦĿ¼������ذ�����
// Ŀ¼��Ļ����ָ��bh��������Ŀ¼���Ŀ¼��i�ڵ�ָ��dir��Ŀ¼��ָ��de���ٸ���
// ��Ŀ¼��de �е�i�ڵ������ iget()�����õ���Ӧ��i�ڵ� inode�������Ӧ·��������
// ��Ŀ¼����Ŀ¼����ڣ����ͷŰ�����Ŀ¼��ĸ��ٻ��������Ż�Ŀ¼�� i�ڵ㣬������
// ���Ѿ����ڳ����룬���˳������ȡĿ¼���i�ڵ��������Ż�Ŀ¼�� i�ڵ㣬���ͷź�
// ��Ŀ¼��ĸ��ٻ����������س����š�
727 bh = find_entry(&dir,basename,namelen,&de);
728 if (!bh) {
729 iput(dir);
730 return -ENOENT;
731 }
732 if (!(inode = iget(dir->i_dev, de->inode))) {
733 iput(dir);
734 brelse(bh);
735 return -ENOENT;
736 }
// ��ʱ�������а���Ҫ��ɾ��Ŀ¼���Ŀ¼i�ڵ�dir��Ҫ��ɾ��Ŀ¼���i�ڵ�inode��Ҫ
// ��ɾ��Ŀ¼��ָ��de����������ͨ������3����������Ϣ�ļ������֤ɾ�������Ŀ����ԡ�
// ����Ŀ¼����������ɾ����־���ҽ��̵���Ч�û�id��euid������root�����ҽ��̵�euid
// �����ڸ�i�ڵ���û�id�����ҽ��̵�euidҲ������Ŀ¼i�ڵ���û�id�����ʾ��ǰ��
// ��û��Ȩ��ɾ����Ŀ¼�����ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬
// Ȼ���ͷŸ��ٻ���飬���س����롣
737 if ((dir->i_mode & S_ISVTX) && !suser() &&
738 current->euid != inode->i_uid &&
739 current->euid != dir->i_uid) {
740 iput(dir);
741 iput(inode);
742 brelse(bh);
743 return -EPERM;
744 }
// �����ָ���ļ�����һ��Ŀ¼����Ҳ����ɾ�����Żظ�Ŀ¼i�ڵ���ļ���Ŀ¼���i��
// �㣬�ͷŰ�����Ŀ¼��Ļ���飬���س����š�
745 if (S_ISDIR(inode->i_mode)) {
746 iput(inode);
747 iput(dir);
748 brelse(bh);
749 return -EPERM;
750 }
// �����i�ڵ�����Ӽ���ֵ�Ѿ�Ϊ0������ʾ������Ϣ����������Ϊ1��
751 if (!inode->i_nlinks) {
752 printk("Deleting nonexistent file (%04x:%d), %d\n",
753 inode->i_dev,inode->i_num,inode->i_nlinks);
754 inode->i_nlinks=1;
755 }
// �������ǿ���ɾ���ļ�����Ӧ��Ŀ¼���ˡ����ǽ����ļ���Ŀ¼���е�i�ڵ���ֶ���Ϊ0��
// ��ʾ�ͷŸ�Ŀ¼������ð�����Ŀ¼��Ļ�������ı�־���ͷŸø��ٻ���顣
756 de->inode = 0;
757 bh->b_dirt = 1;
758 brelse(bh);
// Ȼ����ļ�����Ӧi�ڵ����������1�������ı�־�����¸ı�ʱ��Ϊ��ǰʱ�䡣����
// �ظ�i�ڵ��Ŀ¼��i�ڵ㣬����0���ɹ�����������ļ������һ�����ӣ���i�ڵ�����
// ����1�����0�����Ҵ�ʱû�н��������ļ�����ô�ڵ���iput()�Ż�i�ڵ�ʱ������
// ��Ҳ����ɾ�������ͷ���ռ�õ��豸�ռ䡣�μ�fs/inode.c����183�С�
759 inode->i_nlinks--;
760 inode->i_dirt = 1;
761 inode->i_ctime = CURRENT_TIME;
762 iput(inode);
763 iput(dir);
764 return 0;
765 }
766
//// �����������ӡ�
// Ϊһ���Ѵ����ļ�����һ���������ӣ�Ҳ��Ϊ������ - hard link����
// ������oldname - ԭ·������newname - �µ�·������
// ���أ����ɹ���0�����س����š�
767 int sys_symlink(const char * oldname, const char * newname)
768 {
769 struct dir_entry * de;
770 struct m_inode * dir, * inode;
771 struct buffer_head * bh, * name_block;
772 const char * basename;
773 int namelen, i;
774 char c;
775
// ���Ȳ�����·���������Ŀ¼��i�ڵ�dir�������������ļ������䳤�ȡ����Ŀ¼��
// i�ڵ�û���ҵ����س����š������·�����в������ļ�������Ż���·����Ŀ¼��i
// �ڵ㣬���س����š����⣬����û�û������Ŀ¼��д��Ȩ�ޣ���Ҳ���ܽ������ӣ����Ƿ�
// ����·����Ŀ¼��i�ڵ㣬���س����š�
776 dir = dir_namei(newname,&namelen,&basename, NULL);
777 if (!dir)
778 return -EACCES;
779 if (!namelen) {
780 iput(dir);
781 return -EPERM;
782 }
783 if (!permission(dir,MAY_WRITE)) {
784 iput(dir);
785 return -EACCES;
786 }
// ����������Ŀ¼ָ���豸������һ���µ�i�ڵ㣬�����ø�i�ڵ�ģʽΪ�������������Լ�
// ���̹涨��ģʽ�����롣�������ø�i�ڵ����ı�־��
787 if (!(inode = new_inode(dir->i_dev))) {
788 iput(dir);
789 return -ENOSPC;
790 }
791 inode->i_mode = S_IFLNK | (0777 & ~current->umask);
792 inode->i_dirt = 1;
// Ϊ�˱����������·�����ַ�����Ϣ��������ҪΪ��i�ڵ�����һ�����̿飬����i�ڵ��
// ��1��ֱ�ӿ��i_zone[0]���ڵõ�������š�Ȼ����i�ڵ����ı�־���������ʧ��
// ��Żض�ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬����û�п�
// ��������˳���
793 if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
794 iput(dir);
795 inode->i_nlinks--;
796 iput(inode);
797 return -ENOSPC;
798 }
799 inode->i_dirt = 1;
// Ȼ����豸�϶�ȡ������Ĵ��̿飨Ŀ���ǰѶ�Ӧ��ŵ����ٻ������У�������������Ż�
// ��ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬����û�пռ����
// ���˳���
800 if (!(name_block=bread(inode->i_dev,inode->i_zone[0]))) {
801 iput(dir);
802 inode->i_nlinks--;
803 iput(inode);
804 return -ERROR;
805 }
// �������ǿ��ѷ����������ַ�����������̿����ˡ��̿鳤��Ϊ1024�ֽڣ����Ĭ�Ϸ���
// �������������Ҳֻ����1024�ֽڡ����ǰ��û��ռ��еķ����������ַ������Ƶ��̿�����
// �Ļ�����У����û�������ı�־��Ϊ��ֹ�û��ṩ���ַ���û����null��β�������ڻ�
// ������������һ���ֽڴ�����һ��NULL��Ȼ���ͷŸû���飬������i�ڵ��Ӧ�ļ�����
// �ݳ��ȵ��ڷ����������ַ������ȣ�����i�ڵ����ı�־��
806 i = 0;
807 while (i < 1023 && (c=get_fs_byte(oldname++)))
808 name_block->b_data[i++] = c;
809 name_block->b_data[i] = 0;
810 name_block->b_dirt = 1;
811 brelse(name_block);
812 inode->i_size = i;
813 inode->i_dirt = 1;
// Ȼ����������һ��·����ָ���ķ��������ļ����Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ��
// Ŀ¼��i�ڵ㡣�����Ӧ���������ļ����Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������飬��λ
// �������i�ڵ����Ӽ��������Ż�Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳���
814 bh = find_entry(&dir,basename,namelen,&de);
815 if (bh) {
816 inode->i_nlinks--;
817 iput(inode);
818 brelse(bh);
819 iput(dir);
820 return -EEXIST;
821 }
// ����������ָ��Ŀ¼��������һ��Ŀ¼����ڴ���½����������ļ�����i�ڵ�ź�Ŀ¼
// �������ʧ�ܣ�������Ŀ¼��ĸ��ٻ�����ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻�������
// i�ڵ��������Ӽ�����λ�����Żظ�i�ڵ㡣���س������˳���
822 bh = add_entry(dir,basename,namelen,&de);
823 if (!bh) {
824 inode->i_nlinks--;
825 iput(inode);
826 iput(dir);
827 return -ENOSPC;
828 }
// ��������Ŀ¼���i�ڵ��ֶε�����i�ڵ�ţ����ø��ٻ�������ı�־���ͷŸ��ٻ�
// ��飬�Ż�Ŀ¼���µ�i�ڵ㣬���0���ɹ�����
829 de->inode = inode->i_num;
830 bh->b_dirt = 1;
831 brelse(bh);
832 iput(dir);
833 iput(inode);
834 return 0;
835 }
836
//// Ϊ�ļ�����һ���ļ���Ŀ¼�
// Ϊһ���Ѵ��ڵ��ļ�����һ�������ӣ�Ҳ��ΪӲ���� - hard link����
// ������oldname - ԭ·������newname - �µ�·������
// ���أ����ɹ���0�����س����š�
837 int sys_link(const char * oldname, const char * newname)
838 {
839 struct dir_entry * de;
840 struct m_inode * oldinode, * dir;
841 struct buffer_head * bh;
842 const char * basename;
843 int namelen;
844
// ���ȶ�ԭ�ļ���������Ч����֤����Ӧ�ô��ڲ��Ҳ���һ��Ŀ¼��������������ȡԭ�ļ�·
// ������Ӧ��i�ڵ�oldinode�����Ϊ0�����ʾ���������س����š����ԭ·������Ӧ����
// һ��Ŀ¼������Żظ�i�ڵ㣬Ҳ���س����š�
845 oldinode=namei(oldname);
846 if (!oldinode)
847 return -ENOENT;
848 if (S_ISDIR(oldinode->i_mode)) {
849 iput(oldinode);
850 return -EPERM;
851 }
// Ȼ�������·���������Ŀ¼��i�ڵ�dir�������������ļ������䳤�ȡ����Ŀ¼��
// i�ڵ�û���ҵ�����Ż�ԭ·������i�ڵ㣬���س����š������·�����в������ļ�����
// ��Ż�ԭ·����i�ڵ����·����Ŀ¼��i�ڵ㣬���س����š�
852 dir = dir_namei(newname,&namelen,&basename, NULL);
853 if (!dir) {
854 iput(oldinode);
855 return -EACCES;
856 }
857 if (!namelen) {
858 iput(oldinode);
859 iput(dir);
860 return -EPERM;
861 }
// ���Dz��ܿ��豸����Ӳ���ӡ���������·��������Ŀ¼���豸����ԭ·�������豸��
// ��һ������Ż���·����Ŀ¼��i�ڵ��ԭ·������i�ڵ㣬���س����š����⣬����û�
// û������Ŀ¼��д��Ȩ�ޣ���Ҳ���ܽ������ӣ����ǷŻ���·����Ŀ¼��i�ڵ��ԭ·����
// ��i�ڵ㣬���س����š�
862 if (dir->i_dev != oldinode->i_dev) {
863 iput(dir);
864 iput(oldinode);
865 return -EXDEV;
866 }
867 if (!permission(dir,MAY_WRITE)) {
868 iput(dir);
869 iput(oldinode);
870 return -EACCES;
871 }
// ���ڲ�ѯ����·�����Ƿ��Ѿ����ڣ����������Ҳ���ܽ������ӡ������ͷŰ������Ѵ���Ŀ
// ¼��ĸ��ٻ���飬�Ż���·����Ŀ¼��i�ڵ��ԭ·������i�ڵ㣬���س����š�
872 bh = find_entry(&dir,basename,namelen,&de);
873 if (bh) {
874 brelse(bh);
875 iput(dir);
876 iput(oldinode);
877 return -EEXIST;
878 }
// �������������������ˣ�������������Ŀ¼������һ��Ŀ¼���ʧ����Żظ�Ŀ¼��i��
// ���ԭ·������i�ڵ㣬���س����š������ʼ���ø�Ŀ¼���i�ڵ�ŵ���ԭ·������i
// �ڵ�ţ����ð���������Ŀ¼��Ļ�������ı�־���ͷŸû���飬�Ż�Ŀ¼��i�ڵ㡣
879 bh = add_entry(dir,basename,namelen,&de);
880 if (!bh) {
881 iput(dir);
882 iput(oldinode);
883 return -ENOSPC;
884 }
885 de->inode = oldinode->i_num;
886 bh->b_dirt = 1;
887 brelse(bh);
888 iput(dir);
// �ٽ�ԭ�ڵ�����Ӽ�����1������ı�ʱ��Ϊ��ǰʱ�䣬������i�ڵ����ı�־�����
// �Ż�ԭ·������i�ڵ㣬������0���ɹ�����
889 oldinode->i_nlinks++;
890 oldinode->i_ctime = CURRENT_TIME;
891 oldinode->i_dirt = 1;
892 iput(oldinode);
893 return 0;
894 }
895
1 /*
2 * linux/fs/file_table.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file,buffer_head,m_inode�ȣ���
8
9 struct file file_table[NR_FILE]; // �������(64��)��
10
1 /*
2 * linux/fs/block_dev.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8
9 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
10 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
11 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
12 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
13
// �豸���ݿ�����ָ�����顣ÿ��ָ����ָ��ָ�����豸�ŵ��ܿ�������hd_sizes[]������
// ��������ÿһ���Ӧ���豸��ȷ����һ�����豸����ӵ�е����ݿ�������1���С = 1KB����
14 extern int *blk_size[]; // blk_drv/ll_rw_blk.c��49��
15
//// ���ݿ�д���� - ��ָ���豸�Ӹ���ƫ�ƴ�д��ָ���������ݡ�
// ������dev - �豸�ţ�pos - �豸�ļ���ƫ����ָ�룻buf - �û��ռ��л�������ַ��
// count - Ҫ���͵��ֽ�����
// ������д���ֽ�������û��д���κ��ֽڻ�������س����š�
// �����ں���˵��д����������ٻ�������д�����ݡ�ʲôʱ����������д���豸���ɸ��ٻ�
// �������������������ġ����⣬��Ϊ���豸���Կ�Ϊ��λ���ж�д����˶���д��ʼλ��
// �����ڿ���ʼ��ʱ����Ҫ�Ƚ���ʼ�ֽ����ڵ������������Ȼ����Ҫд�����ݴ�д��ʼ��
// ��д���ÿ飬�ٽ�������һ������д�̣������ɸ��ٻ������ȥ��������
16 int block_write(int dev, long * pos, char * buf, int count)
17 {
// �������ļ���λ��pos����ɿ�ʼ��д�̿�Ŀ����block���������д��1�ֽ��ڸÿ���
// ��ƫ��λ��offset��
18 int block = *pos >> BLOCK_SIZE_BITS; // pos�����ļ����ݿ�š�
19 int offset = *pos & (BLOCK_SIZE-1); // pos�����ݿ���ƫ��ֵ��
20 int chars;
21 int written = 0;
22 int size;
23 struct buffer_head * bh;
24 register char * p; // �ֲ��Ĵ���������������ڼĴ����С�
25
// ��дһ�����豸�ļ�ʱ��Ҫ��д�������ݿ�����Ȼ���ܳ���ָ���豸��������������ݿ���
// ���������������ȡ��ָ���豸�Ŀ�����size���ȽϺ����ƺ�������������д�����ݳ��ȡ�
// ���ϵͳ��û�ж��豸ָ�����ȣ���ʹ��Ĭ�ϳ���0x7fffffff��2GB���飩��
26 if (blk_size[MAJOR(dev)])
27 size = blk_size[MAJOR(dev)][MINOR(dev)];
28 else
29 size = 0x7fffffff;
// Ȼ�����Ҫд����ֽ���count��ѭ��ִ�����²�����ֱ������ȫ��д�롣��ѭ��ִ�й���
// �У�����ǰд�����ݵĿ���Ѿ����ڻ����ָ���豸���ܿ���������д�ֽ������˳���
// Ȼ���ټ����ڵ�ǰ���������ݿ��п�д����ֽ����������Ҫд����ֽ������һ�飬��
// ô��ֻ��дcount�ֽڡ��������Ҫд1���������ݣ���ֱ������1����ٻ���飬������
// �����ݷ��뼴�ɡ��������Ҫ���뽫��д�벿�����ݵ����ݿ飬��Ԥ�����������ݡ�Ȼ��
// ��ŵ��� 1��Ϊ�´β����������������������ʧ�ܣ�����д�ֽ��������û��д
// ���κ��ֽڣ��س����ţ���������
30 while (count>0) {
31 if (block >= size)
32 return written?written:-EIO;
33 chars = BLOCK_SIZE - offset; // �����д����ֽ�����
34 if (chars > count)
35 chars=count;
36 if (chars == BLOCK_SIZE)
37 bh = getblk(dev,block); // buffer.c ��206��322��
38 else
39 bh = breada(dev,block,block+1,block+2,-1);
40 block++;
41 if (!bh)
42 return written?written:-EIO;
// �����Ȱ�ָ��pָ��������ݵĻ�����п�ʼд�����ݵ�λ�ô��������һ��ѭ��д�����
// �ݲ���һ�飬����ӿ鿪ʼ����д���ģ�������ֽڣ����������Ԥ������offsetΪ�㡣
// �˺��ļ���ƫ��ָ��posǰ�ƴ˴ν�Ҫд���ֽ���chars�����ۼ���ЩҪд���ֽ�����ͳ
// ��ֵwritten�С��ٰѻ���Ҫд�ļ���ֵcount ��ȥ�˴�Ҫд���ֽ���chars��Ȼ�����Ǵ�
// �û�����������chars���ֽڵ�pָ��ĸ��ٻ�����п�ʼд���λ�ô���������������
// �û����������ı�־�����ͷŸû�������Ҳ���û��������ü����ݼ�1����
43 p = offset + bh->b_data;
44 offset = 0;
45 *pos += chars;
46 written += chars; // �ۼ�д���ֽ�����
47 count -= chars;
48 while (chars-->0)
49 *(p++) = get_fs_byte(buf++);
50 bh->b_dirt = 1;
51 brelse(bh);
52 }
53 return written; // ������д����ֽ����������˳���
54 }
55
//// ���ݿ������ - ��ָ���豸��λ�ô�����ָ���������ݵ��û��������С�
// ������dev - �豸�ţ�pos - �豸�ļ���ƫ����ָ�룻buf - �û��ռ��л�������ַ��
// count - Ҫ���͵��ֽ�����
// �����Ѷ����ֽ�������û�ж����κ��ֽڻ�������س����š�
56 int block_read(int dev, unsigned long * pos, char * buf, int count)
57 {
58 int block = *pos >> BLOCK_SIZE_BITS;
59 int offset = *pos & (BLOCK_SIZE-1);
60 int chars;
61 int size;
62 int read = 0;
63 struct buffer_head * bh;
64 register char * p; // �ֲ��Ĵ���������������ڼĴ����С�
65
// �ڶ�һ�����豸�ļ�ʱ��Ҫ����������ݿ�����Ȼ���ܳ���ָ���豸��������������ݿ���
// ���������������ȡ��ָ���豸�Ŀ�����size���ȽϺ����ƺ������������Ķ������ݳ��ȡ�
// ���ϵͳ��û�ж��豸ָ�����ȣ���ʹ��Ĭ�ϳ���0x7fffffff��2GB���飩��
66 if (blk_size[MAJOR(dev)])
67 size = blk_size[MAJOR(dev)][MINOR(dev)];
68 else
69 size = 0x7fffffff;
// Ȼ�����Ҫ������ֽ���count��ѭ��ִ�����²�����ֱ������ȫ�����롣��ѭ��ִ�й���
// �У�����ǰ�������ݵĿ���Ѿ����ڻ����ָ���豸���ܿ��������Ѷ��ֽ������˳���
// Ȼ���ټ����ڵ�ǰ���������ݿ����������ֽ����������Ҫ������ֽ���������һ�飬��
// ô��ֻ���count�ֽڡ�Ȼ����ö��麯��breada()������Ҫ�����ݿ飬��Ԥ�����������ݣ�
// ������������������Ѷ��ֽ��������û�ж����κ��ֽڣ��س����š�Ȼ���
// ����1��Ϊ�´β����������������������ʧ�ܣ�����д�ֽ��������û�ж�����
// ���ֽڣ��س����ţ���������
70 while (count>0) {
71 if (block >= size)
72 return read?read:-EIO;
73 chars = BLOCK_SIZE-offset;
74 if (chars > count)
75 chars = count;
76 if (!(bh = breada(dev,block,block+1,block+2,-1)))
77 return read?read:-EIO;
78 block++;
// �����Ȱ�ָ��pָ������̿�Ļ�����п�ʼ�������ݵ�λ�ô��������һ��ѭ����������
// ���ݲ���һ�飬����ӿ���ʼ����ȡ�����ֽڣ����������Ԥ������offsetΪ�㡣 �˺�
// �ļ���ƫ��ָ��posǰ�ƴ˴ν�Ҫ�����ֽ���chars�������ۼ���ЩҪ�����ֽ�����ͳ��ֵ
// read�С��ٰѻ���Ҫ���ļ���ֵcount��ȥ�˴�Ҫ�����ֽ���chars��Ȼ�����ǴӸ��ٻ���
// ����pָ��Ŀ�ʼ����λ�ô�����chars���ֽڵ��û��������У�ͬʱ���û�������ָ��ǰ
// �ơ����θ��������ͷŸû���顣
79 p = offset + bh->b_data;
80 offset = 0;
81 *pos += chars;
82 read += chars; // �ۼƶ����ֽ�����
83 count -= chars;
84 while (chars-->0)
85 put_fs_byte(*(p++),buf++);
86 brelse(bh);
87 }
88 return read; // �����Ѷ�ȡ���ֽ����������˳���
89 }
90
1 /*
2 * linux/fs/file_dev.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8 #include <fcntl.h> // �ļ�����ͷ�ļ��������ļ������������IJ������Ƴ������ŵĶ��塣
9
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݵȡ�
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
13
14 #define MIN(a,b) (((a)<(b))?(a):(b)) // ȡa,b�е���Сֵ��
15 #define MAX(a,b) (((a)>(b))?(a):(b)) // ȡa,b�е����ֵ��
16
//// �ļ������� - ����i�ڵ���ļ��ṹ����ȡ�ļ������ݡ�
// ��i�ڵ����ǿ���֪���豸�ţ���filp�ṹ����֪���ļ��е�ǰ��дָ��λ�á�bufָ����
// ���ռ��л�������λ�ã�count����Ҫ��ȡ���ֽ����� ����ֵ��ʵ�ʶ�ȡ���ֽ����������
// �ţ�С��0����
17 int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)
18 {
19 int left,chars,nr;
20 struct buffer_head * bh;
21
// �����жϲ�������Ч�ԡ�����Ҫ��ȡ���ֽڼ���countС�ڵ����㣬��0��������Ҫ��
// ȡ���ֽ���������0����ѭ��ִ�����������ֱ������ȫ���������������⡣�ڶ�ѭ������
// �����У����Ǹ���i�ڵ���ļ����ṹ��Ϣ�������� bmap() �õ������ļ���ǰ��дλ�õ�
// ���ݿ����豸�϶�Ӧ�������nr����nr��Ϊ0�����i�ڵ�ָ�����豸�϶�ȡ�����顣
// ���������ʧ�����˳�ѭ������nrΪ0����ʾָ�������ݿ鲻���ڣ��û����ָ��ΪNULL��
// (filp->f_pos)/BLOCK_SIZE ���ڼ�����ļ���ǰָ���������ݿ�š�
22 if ((left=count)<=0)
23 return 0;
24 while (left) {
25 if (nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE)) { // inode.c��140��
26 if (!(bh=bread(inode->i_dev,nr)))
27 break;
28 } else
29 bh = NULL;
// �������Ǽ����ļ���дָ�������ݿ��е�ƫ��ֵnr�����ڸ����ݿ�������ϣ����ȡ���ֽ���
// Ϊ (BLOCK_SIZE - nr)��Ȼ������ڻ����ȡ���ֽ���left���Ƚϣ�����Сֵ��Ϊ���β���
// ���ȡ���ֽ���chars����� (BLOCK_SIZE - nr) > left����˵���ÿ�����Ҫ��ȡ�����һ
// �����ݣ���֮����Ҫ��ȡ��һ�����ݡ�֮�������д�ļ�ָ�롣 ָ��ǰ�ƴ˴ν���ȡ����
// ����chars��ʣ���ֽڼ���left��Ӧ��ȥchars��
30 nr = filp->f_pos % BLOCK_SIZE;
31 chars = MIN( BLOCK_SIZE-nr , left );
32 filp->f_pos += chars;
33 left -= chars;
// ��������豸�϶��������ݣ���pָ����п�ʼ��ȡ���ݵ�λ�ã����Ҹ���chars�ֽ�
// ���û�������buf�С��������û�������������chars��0ֵ�ֽڡ�
34 if (bh) {
35 char * p = nr + bh->b_data;
36 while (chars-->0)
37 put_fs_byte(*(p++),buf++);
38 brelse(bh);
39 } else {
40 while (chars-->0)
41 put_fs_byte(0,buf++);
42 }
43 }
// �ĸ�i�ڵ�ķ���ʱ��Ϊ��ǰʱ�䡣���ض�ȡ���ֽ���������ȡ�ֽ���Ϊ0���س����š�
// CURRENT_TIME�Ƕ�����include/linux/sched.h��142���ϵĺ꣬���ڼ���UNIXʱ�䡣����
// 1970��1��1��0ʱ0�뿪ʼ������ǰ��ʱ�䡣��λ���롣
44 inode->i_atime = CURRENT_TIME;
45 return (count-left)?(count-left):-ERROR;
46 }
47
//// �ļ�д���� - ����i�ڵ���ļ��ṹ��Ϣ�����û�����д���ļ��С�
// ��i�ڵ����ǿ���֪���豸�ţ�����file�ṹ����֪���ļ��е�ǰ��дָ��λ�á�bufָ��
// �û�̬�л�������λ�ã�countΪ��Ҫд����ֽ����� ����ֵ��ʵ��д����ֽ����������
// �ţ�С��0����
48 int file_write(struct m_inode * inode, struct file * filp, char * buf, int count)
49 {
50 off_t pos;
51 int block,c;
52 struct buffer_head * bh;
53 char * p;
54 int i=0;
55
56 /*
57 * ok, append may not work when many processes are writing at the same time
58 * but so what. That way leads to madness anyway.
59 */
/*
* ok�����������ͬʱдʱ��append�������ܲ��У�����������������������������
* ���»���һ�š�
*/
// ����ȷ������д���ļ���λ�á������Ҫ���ļ����������ݣ����ļ���дָ���Ƶ��ļ�β
// ��������ͽ����ļ���ǰ��дָ�봦д�롣
60 if (filp->f_flags & O_APPEND)
61 pos = inode->i_size;
62 else
63 pos = filp->f_pos;
// Ȼ������д���ֽ���i���տ�ʼʱΪ0��С��ָ��д���ֽ���countʱ��ѭ��ִ�����²�����
// ��ѭ�����������У�������ȡ�ļ����ݿ�� ( pos/BLOCK_SIZE ) ���豸�϶�Ӧ�������
// block�������Ӧ�����鲻���ھʹ���һ�顣����õ�������� = 0�����ʾ����ʧ�ܣ�
// �����˳�ѭ�����������Ǹ��ݸ�����Ŷ�ȡ�豸�ϵ���Ӧ���飬������Ҳ�˳�ѭ����
64 while (i<count) {
65 if (!(block = create_block(inode,pos/BLOCK_SIZE)))
66 break;
67 if (!(bh=bread(inode->i_dev,block)))
68 break;
// ��ʱ�����ָ��bh��ָ��ն�����ļ����ݿ顣����������ļ���ǰ��дָ���ڸ����ݿ���
// ��ƫ��ֵc������ָ��pָ����п�ʼд�����ݵ�λ�ã����øû�������ı�־������
// ���е�ǰָ�룬�ӿ�ʼ��дλ�õ���ĩ����д��c =(BLOCK_SIZE - c)���ֽڡ���c����ʣ��
// ����д����ֽ��� (count - i)����˴�ֻ����д��c = (count - i)���ֽڼ��ɡ�
69 c = pos % BLOCK_SIZE;
70 p = c + bh->b_data;
71 bh->b_dirt = 1;
72 c = BLOCK_SIZE-c;
73 if (c > count-i) c = count-i;
// ��д������֮ǰ��������Ԥ�����ú���һ��ѭ������Ҫ��д�ļ��е�λ�á�������ǰ�pos
// ָ��ǰ�ƴ˴���д����ֽ����������ʱposλ��ֵ�������ļ���ǰ���ȣ�����i�ڵ���
// �ļ������ֶΣ�����i�ڵ����ı�־��Ȼ��Ѵ˴�Ҫд����ֽ���c�ۼӵ���д���ֽڼ�
// ��ֵi�У���ѭ���ж�ʹ�á����Ŵ��û�������buf�и���c���ֽڵ����ٻ������pָ��
// �Ŀ�ʼλ�ô������������ͷŸû���顣
74 pos += c;
75 if (pos > inode->i_size) {
76 inode->i_size = pos;
77 inode->i_dirt = 1;
78 }
79 i += c;
80 while (c-->0)
81 *(p++) = get_fs_byte(buf++);
82 brelse(bh);
83 }
// �������Ѿ�ȫ��д���ļ�������д���������з�������ʱ�ͻ��˳�ѭ������ʱ���Ǹ����ļ�
// ��ʱ��Ϊ��ǰʱ�䣬�������ļ���дָ�롣����˴β����������ļ�β�������ݣ������
// ����дָ���������ǰ��дλ��pos�����������ļ�i�ڵ����ʱ��Ϊ��ǰʱ�䡣���
// ��д����ֽ�������д���ֽ���Ϊ0���س�����-1��
84 inode->i_mtime = CURRENT_TIME;
85 if (!(filp->f_flags & O_APPEND)) {
86 filp->f_pos = pos;
87 inode->i_ctime = CURRENT_TIME;
88 }
89 return (i?i:-1);
90 }
91
1 /*
2 * linux/fs/pipe.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ����������ԭ�͡�
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <termios.h> // �ն������������ͷ�ļ�����Ҫ��������첽ͨ�ſڵ��ն˽ӿڡ�
10
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
12 #include <linux/mm.h> /* for get_free_page */ /* ʹ�����е�get_free_page */
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
15
//// �ܵ�������������
// ����inode�ǹܵ���Ӧ��i�ڵ㣬buf���û����ݻ�����ָ�룬count�Ƕ�ȡ���ֽ�����
16 int read_pipe(struct m_inode * inode, char * buf, int count)
17 {
18 int chars, size, read = 0;
19
// �����Ҫ��ȡ���ֽڼ���count����0�����Ǿ�ѭ��ִ�����²�������ѭ�������������У�
// ����ǰ�ܵ���û�����ݣ�size=0�������ѵȴ��ýڵ�Ľ��̣���ͨ����д�ܵ����̡����
// ��û��д�ܵ��ߣ��� i�ڵ����ü���ֵС��2�����Ѷ��ֽ����˳��������ǰ�յ��з�
// �����źţ������̷����Ѷ�ȡ�ֽ����˳�������û���յ��κ����ݣ�����������ϵͳ
// ���ú��˳���������ý����ڸùܵ���˯�ߣ����Եȴ���Ϣ�ĵ�������PIPE_SIZE������
// include/linux/fs.h�С����ڡ���������ϵͳ���á�����μ�kernel/signal.c����
20 while (count>0) {
21 while (!(size=PIPE_SIZE(*inode))) { // ȡ�ܵ������ݳ���ֵ��
22 wake_up(& PIPE_WRITE_WAIT(*inode));
23 if (inode->i_count != 2) /* are there any writers? */
24 return read;
25 if (current->signal & ~current->blocked)
26 return read?read:-ERESTARTSYS;
27 interruptible_sleep_on(& PIPE_READ_WAIT(*inode));
28 }
// ��ʱ˵���ܵ������������������ݡ���������ȡ�ܵ�βָ�뵽������ĩ�˵��ֽ���chars��
// �������ڻ���Ҫ��ȡ���ֽ���count�����������count�����chars���ڵ�ǰ�ܵ��к�
// �����ݵij��� size����������� size�� Ȼ�������ֽ���count��ȥ�˴οɶ����ֽ���
// chars�����ۼ��Ѷ��ֽ���read��
29 chars = PAGE_SIZE-PIPE_TAIL(*inode);
30 if (chars > count)
31 chars = count;
32 if (chars > size)
33 chars = size;
34 count -= chars;
35 read += chars;
// ����sizeָ��ܵ�βָ�봦����������ǰ�ܵ�βָ�루ǰ��chars�ֽڣ�����βָ�볬��
// �ܵ�ĩ�����ƻء�Ȼ�ܵ��е����ݸ��Ƶ��û��������С����ڹܵ�i�ڵ㣬��i_size
// �ֶ����ǹܵ������ָ�롣
36 size = PIPE_TAIL(*inode);
37 PIPE_TAIL(*inode) += chars;
38 PIPE_TAIL(*inode) &= (PAGE_SIZE-1);
39 while (chars-->0)
40 put_fs_byte(((char *)inode->i_size)[size++],buf++);
41 }
// ���˴ζ��ܵ��������������ѵȴ��ùܵ��Ľ��̣������ض�ȡ���ֽ�����
42 wake_up(& PIPE_WRITE_WAIT(*inode));
43 return read;
44 }
45
//// �ܵ�д����������
// ����inode�ǹܵ���Ӧ��i�ڵ㣬buf�����ݻ�����ָ�룬count�ǽ�д��ܵ����ֽ�����
46 int write_pipe(struct m_inode * inode, char * buf, int count)
47 {
48 int chars, size, written = 0;
49
// ���Ҫд����ֽ���count������0����ô���Ǿ�ѭ��ִ�����²�������ѭ�����������У�
// �����ǰ�ܵ����Ѿ����ˣ����пռ� size = 0�������ѵȴ��ùܵ��Ľ��̣�ͨ������
// ���Ƕ��ܵ����̡� �����û�ж��ܵ��ߣ���i�ڵ����ü���ֵС��2������ǰ���̷���
// SIGPIPE�źţ���������д����ֽ����˳�����д��0�ֽڣ��� -1�������õ�ǰ����
// �ڸùܵ���˯�ߣ��Եȴ����ܵ���������ȡ���ݣ��Ӷ��ùܵ��ڳ��ռ䡣��PIPE_SIZE()��
// PIPE_HEAD()�ȶ������ļ�include/linux/fs.h�С�
50 while (count>0) {
51 while (!(size=(PAGE_SIZE-1)-PIPE_SIZE(*inode))) {
52 wake_up(& PIPE_READ_WAIT(*inode));
53 if (inode->i_count != 2) { /* no readers */
54 current->signal |= (1<<(SIGPIPE-1));
55 return written?written:-1;
56 }
57 sleep_on(& PIPE_WRITE_WAIT(*inode));
58 }
// ����ִ�е������ʾ�ܵ����������п�д�ռ�size����������ȡ�ܵ�ͷָ�뵽������ĩ�˿�
// ���ֽ���chars��д�ܵ������Ǵӹܵ�ͷָ�봦��ʼд�ġ����chars���ڻ���Ҫд����ֽ�
// ��count����������� count�� ��� chars���ڵ�ǰ�ܵ��п��пռ䳤��size�����������
// size��Ȼ�����Ҫд���ֽ���count��ȥ�˴ο�д����ֽ���chars������д���ֽ����ۼӵ�
// written�С�
59 chars = PAGE_SIZE-PIPE_HEAD(*inode);
60 if (chars > count)
61 chars = count;
62 if (chars > size)
63 chars = size;
64 count -= chars;
65 written += chars;
// ����sizeָ��ܵ�����ͷָ�봦����������ǰ�ܵ�����ͷ��ָ�루ǰ��chars�ֽڣ�����ͷ
// ָ�볬���ܵ�ĩ�����ƻء�Ȼ����û�����������chars���ֽڵ��ܵ�ͷָ�뿪ʼ���� ����
// �ܵ�i�ڵ㣬��i_size�ֶ����ǹܵ������ָ�롣
66 size = PIPE_HEAD(*inode);
67 PIPE_HEAD(*inode) += chars;
68 PIPE_HEAD(*inode) &= (PAGE_SIZE-1);
69 while (chars-->0)
70 ((char *)inode->i_size)[size++]=get_fs_byte(buf++);
71 }
// ���˴�д�ܵ��������������ѵȴ��ܵ��Ľ��̣�������д����ֽ������˳���
72 wake_up(& PIPE_READ_WAIT(*inode));
73 return written;
74 }
75
//// �����ܵ�ϵͳ���á�
// ��fildes��ָ�������д���һ���ļ��������������������ļ����ָ��һ�ܵ�i�ڵ㡣
// ������filedes -�ļ�������顣fildes[0]���ڶ��ܵ����ݣ�fildes[1]��ܵ�д�����ݡ�
// �ɹ�ʱ����0������ʱ����-1��
76 int sys_pipe(unsigned long * fildes)
77 {
78 struct m_inode * inode;
79 struct file * f[2]; // �ļ��ṹ���顣
80 int fd[2]; // �ļ�������顣
81 int i,j;
82
// ���ȴ�ϵͳ�ļ�����ȡ������������ü����ֶ�Ϊ0��������ֱ��������ü���Ϊ1��
// ��ֻ��1����������ͷŸ�����ü�����λ������û���ҵ������������ -1��
83 j=0;
84 for(i=0;j<2 && i<NR_FILE;i++)
85 if (!file_table[i].f_count)
86 (f[j++]=i+file_table)->f_count++;
87 if (j==1)
88 f[0]->f_count=0;
89 if (j<2)
90 return -1;
// �������ȡ�õ������ļ����ṹ��ֱ����һ�ļ�����ţ���ʹ�����ļ��ṹָ�������
// ����ֱ�ָ���������ļ��ṹ�����ļ�������Ǹ�����������š����Ƶأ����ֻ��һ����
// ���ļ���������ͷŸþ�����ÿ���Ӧ����������û���ҵ��������о�������ͷ�����
// ��ȡ�������ļ��ṹ���λ���ü���ֵ���������� -1��
91 j=0;
92 for(i=0;j<2 && i<NR_OPEN;i++)
93 if (!current->filp[i]) {
94 current->filp[ fd[j]=i ] = f[j];
95 j++;
96 }
97 if (j==1)
98 current->filp[fd[0]]=NULL;
99 if (j<2) {
100 f[0]->f_count=f[1]->f_count=0;
101 return -1;
102 }
// Ȼ�����ú���get_pipe_inode()����һ���ܵ�ʹ�õ�i�ڵ㣬��Ϊ�ܵ�����һҳ�ڴ���Ϊ��
// ������������ɹ�������Ӧ�ͷ������ļ�������ļ��ṹ�������-1��
103 if (!(inode=get_pipe_inode())) { // fs/inode.c����231�п�ʼ����
104 current->filp[fd[0]] =
105 current->filp[fd[1]] = NULL;
106 f[0]->f_count = f[1]->f_count = 0;
107 return -1;
108 }
// ����ܵ�i�ڵ�����ɹ�����������ļ��ṹ���г�ʼ�������������Ƕ�ָ��ͬһ���ܵ�i��
// �㣬���Ѷ�дָ�붼���㡣��1���ļ��ṹ���ļ�ģʽ��Ϊ������2���ļ��ṹ���ļ�ģʽ��
// Ϊд������ļ�������鸴�Ƶ���Ӧ���û��ռ������У��ɹ�����0���˳���
109 f[0]->f_inode = f[1]->f_inode = inode;
110 f[0]->f_pos = f[1]->f_pos = 0;
111 f[0]->f_mode = 1; /* read */
112 f[1]->f_mode = 2; /* write */
113 put_fs_long(fd[0],0+fildes);
114 put_fs_long(fd[1],1+fildes);
115 return 0;
116 }
117
//// �ܵ�io���ƺ�����
// ������pino - �ܵ�i�ڵ�ָ�룻cmd - �������arg - ������
// ��������0��ʾִ�гɹ������س����롣
118 int pipe_ioctl(struct m_inode *pino, int cmd, int arg)
119 {
// ���������ȡ�ܵ��е�ǰ�ɶ����ݳ��ȣ���ѹܵ����ݳ���ֵ�����û�����ָ����λ�ô���
// ������0��������Ч��������롣
120 switch (cmd) {
121 case FIONREAD:
122 verify_area((void *) arg,4);
123 put_fs_long(PIPE_SIZE(*pino),(unsigned long *) arg);
124 return 0;
125 default:
126 return -EINVAL;
127 }
128 }
129
1 /*
2 * linux/fs/char_dev.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
9
10 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14 #include <asm/io.h> // ioͷ�ļ�������Ӳ���˿�����/���������䡣
15
16 extern int tty_read(unsigned minor,char * buf,int count); // �ն˶���
17 extern int tty_write(unsigned minor,char * buf,int count); // �ն�д��
18
// �����ַ��豸��д����ָ�����͡�
19 typedef (*crw_ptr)(int rw,unsigned minor,char * buf,int count,off_t * pos);
20
//// �����ն˶�д����������
// ������rw - ��д���minor - �ն����豸�ţ�buf - ��������cout - ��д�ֽ�����
// pos - ��д������ǰָ�룬�����ն˲�������ָ�����á�
// ���أ�ʵ�ʶ�д���ֽ�������ʧ���س����롣
21 static int rw_ttyx(int rw,unsigned minor,char * buf,int count,off_t * pos)
22 {
23 return ((rw==READ)?tty_read(minor,buf,count):
24 tty_write(minor,buf,count));
25 }
26
//// �ն˶�д����������
// ͬ��rw_ttyx()��ֻ�������˶Խ����Ƿ��п����ն˵ļ�⡣
27 static int rw_tty(int rw,unsigned minor,char * buf,int count, off_t * pos)
28 {
// ������û�ж�Ӧ�Ŀ����նˣ��س����š���������ն˶�д����rw_ttyx()��������
// ʵ�ʶ�д�ֽ�����
29 if (current->tty<0)
30 return -EPERM;
31 return rw_ttyx(rw,current->tty,buf,count,pos);
32 }
33
//// �ڴ����ݶ�д��δʵ�֡�
34 static int rw_ram(int rw,char * buf, int count, off_t *pos)
35 {
36 return -EIO;
37 }
38
//// �����ڴ����ݶ�д����������δʵ�֡�
39 static int rw_mem(int rw,char * buf, int count, off_t * pos)
40 {
41 return -EIO;
42 }
43
//// �ں������ڴ����ݶ�д������δʵ�֡�
44 static int rw_kmem(int rw,char * buf, int count, off_t * pos)
45 {
46 return -EIO;
47 }
48
// �˿ڶ�д����������
// ������rw - ��д���buf - ��������cout - ��д�ֽ�����pos - �˿ڵ�ַ��
// ���أ�ʵ�ʶ�д���ֽ�����
49 static int rw_port(int rw,char * buf, int count, off_t * pos)
50 {
51 int i=*pos;
52
// ������Ҫ���д���ֽ��������Ҷ˿ڵ�ַС��64kʱ��ѭ��ִ�е����ֽڵĶ�д������
// ���Ƕ������Ӷ˿�i�ж�ȡһ�ֽ����ݲ��ŵ��û��������С�����д��������
// �����ݻ�������ȡһ�ֽ�������˿�i��
53 while (count-->0 && i<65536) {
54 if (rw==READ)
55 put_fs_byte(inb(i),buf++);
56 else
57 outb(get_fs_byte(buf++),i);
58 i++; // ǰ��һ���˿ڡ�[??]
59 }
// Ȼ������/д���ֽ�����������Ӧ��дָ�룬�����ض�/д���ֽ�����
60 i -= *pos;
61 *pos += i;
62 return i;
63 }
64
//// �ڴ��д�����������ڴ����豸����1�������������0-5���豸�Ĵ�����
65 static int rw_memory(int rw, unsigned minor, char * buf, int count, off_t * pos)
66 {
// �����ڴ��豸���豸�ţ��ֱ���ò�ͬ���ڴ��д������
67 switch(minor) {
68 case 0: // ��Ӧ�豸�ļ����� /dev/ram0��/dev/ramdisk��
69 return rw_ram(rw,buf,count,pos);
70 case 1: // /dev/ram1��/dev/mem��ram��
71 return rw_mem(rw,buf,count,pos);
72 case 2: // /dev/ram2��/dev/kmem��
73 return rw_kmem(rw,buf,count,pos);
74 case 3: // /dev/null��
75 return (rw==READ)?0:count; /* rw_null */
76 case 4: // /dev/port��
77 return rw_port(rw,buf,count,pos);
78 default:
79 return -EIO;
80 }
81 }
82
// ����ϵͳ���豸������
83 #define NRDEVS ((sizeof (crw_table))/(sizeof (crw_ptr)))
84
// �ַ��豸��д����ָ�����
85 static crw_ptr crw_table[]={
86 NULL, /* nodev */ /* ���豸(���豸) */
87 rw_memory, /* /dev/mem etc */ /* /dev/mem�� */
88 NULL, /* /dev/fd */ /* /dev/fd���� */
89 NULL, /* /dev/hd */ /* /dev/hdӲ�� */
90 rw_ttyx, /* /dev/ttyx */ /* /dev/ttyx�����ն� */
91 rw_tty, /* /dev/tty */ /* /dev/tty�ն� */
92 NULL, /* /dev/lp */ /* /dev/lp��ӡ�� */
93 NULL}; /* unnamed pipes */ /* δ�����ܵ� */
94
//// �ַ��豸��д����������
// ������rw -��д���dev -�豸�ţ�buf -��������count -��д�ֽ�����pos -��дָ�롣
// ���أ�ʵ�ʶ�/д�ֽ�����
95 int rw_char(int rw,int dev, char * buf, int count, off_t * pos)
96 {
97 crw_ptr call_addr;
98
// ����豸�ų���ϵͳ�豸�����س����롣������豸û�ж�Ӧ�Ķ�/д������Ҳ���س�
// ���롣������ö�Ӧ�豸�Ķ�д����������������ʵ�ʶ�/д���ֽ�����
99 if (MAJOR(dev)>=NRDEVS)
100 return -ENODEV;
101 if (!(call_addr=crw_table[MAJOR(dev)]))
102 return -ENODEV;
103 return call_addr(rw,MINOR(dev),buf,count,pos);
104 }
105
1 /*
2 * linux/fs/read_write.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
10
11 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
12 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14
// �ַ��豸��д������fs/char_dev.c����95�С�
15 extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos);
// ���ܵ�����������fs/pipe.c����13�С�
16 extern int read_pipe(struct m_inode * inode, char * buf, int count);
// д�ܵ�����������fs/pipe.c����41�С�
17 extern int write_pipe(struct m_inode * inode, char * buf, int count);
// ���豸������������fs/block_dev.c����47�С�
18 extern int block_read(int dev, off_t * pos, char * buf, int count);
// ���豸д����������fs/block_dev.c����14�С�
19 extern int block_write(int dev, off_t * pos, char * buf, int count);
// ���ļ�����������fs/file_dev.c����17�С�
20 extern int file_read(struct m_inode * inode, struct file * filp,
21 char * buf, int count);
// д�ļ�����������fs/file_dev.c����48�С�
22 extern int file_write(struct m_inode * inode, struct file * filp,
23 char * buf, int count);
24
//// �ض�λ�ļ���дָ��ϵͳ���á�
// ����fd���ļ������offset���µ��ļ���дָ��ƫ��ֵ��origin��ƫ�Ƶ���ʼλ�ã�����
// ����ѡ��SEEK_SET��0�����ļ���ʼ������SEEK_CUR��1���ӵ�ǰ��дλ�ã���SEEK_END��
// 2�����ļ�β������
25 int sys_lseek(unsigned int fd,off_t offset, int origin)
26 {
27 struct file * file;
28 int tmp;
29
// �����жϺ����ṩ�IJ�����Ч�ԡ�����ļ����ֵ���ڳ��������ļ���NR_OPEN(20)��
// ���߸þ�����ļ��ṹָ��Ϊ�գ����߶�Ӧ�ļ��ṹ��i�ڵ��ֶ�Ϊ�գ�����ָ���豸�ļ�
// ָ���Dz��ɶ�λ�ģ��س����벢�˳�������ļ���Ӧ��i�ڵ��ǹܵ��ڵ㣬�س���
// ���˳�����Ϊ�ܵ�ͷβָ�벻�������ƶ���
30 if (fd >= NR_OPEN || !(file=current->filp[fd]) || !(file->f_inode)
31 || !IS_SEEKABLE(MAJOR(file->f_inode->i_dev)))
32 return -EBADF;
33 if (file->f_inode->i_pipe)
34 return -ESPIPE;
// Ȼ��������õĶ�λ��־���ֱ����¶�λ�ļ���дָ�롣
35 switch (origin) {
// origin = SEEK_SET��Ҫ�����ļ���ʼ����Ϊԭ�������ļ���дָ�롣��ƫ��ֵС���㣬���
// �����ش����롣���������ļ���дָ�����offset��
36 case 0:
37 if (offset<0) return -EINVAL;
38 file->f_pos=offset;
39 break;
// origin = SEEK_CUR��Ҫ�����ļ���ǰ��дָ�봦��Ϊԭ���ض�λ��дָ�롣����ļ���ǰָ
// �����ƫ��ֵС��0���س������˳��������ڵ�ǰ��дָ���ϼ���ƫ��ֵ��
40 case 1:
41 if (file->f_pos+offset<0) return -EINVAL;
42 file->f_pos += offset;
43 break;
// origin = SEEK_END��Ҫ�����ļ�ĩβ��Ϊԭ���ض�λ��дָ�롣��ʱ���ļ���С����ƫ��ֵ
// С�����س������˳��������ض�λ��дָ��Ϊ�ļ����ȼ���ƫ��ֵ��
44 case 2:
45 if ((tmp=file->f_inode->i_size+offset) < 0)
46 return -EINVAL;
47 file->f_pos = tmp;
48 break;
// ��origin ������Ч�����س������˳���
49 default:
50 return -EINVAL;
51 }
52 return file->f_pos; // ����ض�λ����ļ���дָ��ֵ��
53 }
54
//// ���ļ�ϵͳ���á�
// ����fd���ļ������buf�ǻ�������count�������ֽ�����
55 int sys_read(unsigned int fd,char * buf,int count)
56 {
57 struct file * file;
58 struct m_inode * inode;
59
// �������ȶԲ�����Ч�Խ����жϡ�����ļ����ֵ���ڳ��������ļ���NR_OPEN������
// ��Ҫ��ȡ���ֽڼ���ֵС��0�����߸þ�����ļ��ṹָ��Ϊ�գ��س����벢�˳�����
// ���ȡ���ֽ���count����0����0�˳�
60 if (fd>=NR_OPEN || count<0 || !(file=current->filp[fd]))
61 return -EINVAL;
62 if (!count)
63 return 0;
// Ȼ����֤������ݵĻ������ڴ����ơ���ȡ�ļ���i�ڵ㡣���ڸ��ݸ�i�ڵ�����ԣ��ֱ�
// ������Ӧ�Ķ��������������ǹܵ��ļ��������Ƕ��ܵ��ļ�ģʽ������ж��ܵ�����������
// ���ض�ȡ���ֽ��������س����룬�˳���������ַ����ļ�������ж��ַ��豸��
// ���������ض�ȡ���ַ���������ǿ��豸�ļ�����ִ�п��豸�������������ض�ȡ���ֽ�����
64 verify_area(buf,count);
65 inode = file->f_inode;
66 if (inode->i_pipe)
67 return (file->f_mode&1)?read_pipe(inode,buf,count):-EIO;
68 if (S_ISCHR(inode->i_mode))
69 return rw_char(READ,inode->i_zone[0],buf,count,&file->f_pos);
70 if (S_ISBLK(inode->i_mode))
71 return block_read(inode->i_zone[0],&file->f_pos,buf,count);
// �����Ŀ¼�ļ������dz����ļ�����������֤��ȡ�ֽ���count����Ч�Բ����е���������
// ȡ�ֽ��������ļ���ǰ��дָ��ֵ�����ļ����ȣ����������ö�ȡ�ֽ���Ϊ �ļ�����-��ǰ
// ��дָ��ֵ������ȡ������0����0�˳�����Ȼ��ִ���ļ������������ض�ȡ���ֽ���
// ���˳���
72 if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
73 if (count+file->f_pos > inode->i_size)
74 count = inode->i_size - file->f_pos;
75 if (count<=0)
76 return 0;
77 return file_read(inode,file,buf,count);
78 }
// ִ�е����˵���������ж��ļ������ԡ����ӡ�ڵ��ļ����ԣ������س������˳���
79 printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode);
80 return -EINVAL;
81 }
82
//// д�ļ�ϵͳ���á�
// ����fd���ļ������buf���û���������count����д�ֽ�����
83 int sys_write(unsigned int fd,char * buf,int count)
84 {
85 struct file * file;
86 struct m_inode * inode;
87
// ͬ���أ����������жϺ�����������Ч�ԡ���������ļ����ֵ���ڳ��������ļ���
// NR_OPEN��������Ҫд����ֽڼ���С��0�����߸þ�����ļ��ṹָ��Ϊ�գ��س���
// �벢�˳���������ȡ���ֽ���count����0����0�˳�
88 if (fd>=NR_OPEN || count <0 || !(file=current->filp[fd]))
89 return -EINVAL;
90 if (!count)
91 return 0;
// Ȼ����֤������ݵĻ������ڴ����ơ���ȡ�ļ���i�ڵ㡣���ڸ��ݸ�i�ڵ�����ԣ��ֱ�
// ������Ӧ�Ķ��������������ǹܵ��ļ���������д�ܵ��ļ�ģʽ�������д�ܵ�����������
// ����д����ֽ��������س������˳���������ַ��豸�ļ��������д�ַ��豸��
// ��������д����ַ����˳�������ǿ��豸�ļ�������п��豸д������������д����ֽ�
// ���˳������dz����ļ�����ִ���ļ�д������������д����ֽ������˳���
92 inode=file->f_inode;
93 if (inode->i_pipe)
94 return (file->f_mode&2)?write_pipe(inode,buf,count):-EIO;
95 if (S_ISCHR(inode->i_mode))
96 return rw_char(WRITE,inode->i_zone[0],buf,count,&file->f_pos);
97 if (S_ISBLK(inode->i_mode))
98 return block_write(inode->i_zone[0],&file->f_pos,buf,count);
99 if (S_ISREG(inode->i_mode))
100 return file_write(inode,file,buf,count);
// ִ�е����˵���������ж��ļ������ԡ����ӡ�ڵ��ļ����ԣ������س������˳���
101 printk("(Write)inode->i_mode=%06o\n\r",inode->i_mode);
102 return -EINVAL;
103 }
104
1 /*
2 * linux/fs/open.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <fcntl.h> // �ļ�����ͷ�ļ��������ļ������������������Ƴ������Ŷ��塣
10 #include <sys/types.h> // ����ͷ�ļ������������ϵͳ���ļ�ϵͳͳ����Ϣ�ṹ�����͡�
11 #include <utime.h> // �û�ʱ��ͷ�ļ���������ʺ���ʱ��ṹ�Լ�utime()ԭ�͡�
12 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͷ��ų����ȡ�
13
14 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
15 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
16 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
17
18 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
19
//// ȡ�ļ�ϵͳ��Ϣ��
// ����dev�Ǻ����Ѱ�װ�ļ�ϵͳ���豸�š�ubuf��һ��ustat�ṹ������ָ�룬���ڴ��
// ϵͳ���ص��ļ�ϵͳ��Ϣ����ϵͳ�������ڷ����Ѱ�װ��mounted���ļ�ϵͳ��ͳ����Ϣ��
// �ɹ�ʱ����0������ubufָ���ustate�ṹ�������ļ�ϵͳ�ܿ��п����Ϳ���i�ڵ�����
// ustat�ṹ������include/sys/types.h�С�
20 int sys_ustat(int dev, struct ustat * ubuf)
21 {
22 return -ENOSYS; // �����룺���ܻ�δʵ�֡�
23 }
24
//// �����ļ����ʺ���ʱ�䡣
// ����filename���ļ�����times�Ƿ��ʺ���ʱ��ṹָ�롣
// ���timesָ�벻ΪNULL����ȡutimbuf�ṹ�е�ʱ����Ϣ�������ļ��ķ��ʺ���ʱ�䡣
// ���timesָ����NULL����ȡϵͳ��ǰʱ��������ָ���ļ��ķ��ʺ���ʱ����
25 int sys_utime(char * filename, struct utimbuf * times)
26 {
27 struct m_inode * inode;
28 long actime,modtime;
29
// �ļ���ʱ����Ϣ��������i�ڵ��ӡ�����������ȸ����ļ���ȡ�ö�Ӧi�ڵ㡣���û����
// �����س����롣����ṩ�ķ��ʺ���ʱ��ṹָ��times��ΪNULL����ӽṹ�ж�ȡ
// �û����õ�ʱ��ֵ���������ϵͳ��ǰʱ���������ļ��ķ��ʺ���ʱ�䡣
30 if (!(inode=namei(filename)))
31 return -ENOENT;
32 if (times) {
33 actime = get_fs_long((unsigned long *) ×->actime);
34 modtime = get_fs_long((unsigned long *) ×->modtime);
35 } else
36 actime = modtime = CURRENT_TIME;
// Ȼ����i�ڵ��еķ���ʱ���ֶκ���ʱ���ֶΡ�������i�ڵ����ı�־���Żظ�i��
// �㣬������0��
37 inode->i_atime = actime;
38 inode->i_mtime = modtime;
39 inode->i_dirt = 1;
40 iput(inode);
41 return 0;
42 }
43
44 /*
45 * XXX should we use the real or effective uid? BSD uses the real uid,
46 * so as to make this call useful to setuid programs.
47 */
/*
* XXX ���Ǹ�����ʵ�û�id��ruid��������Ч�û�id��euid����BSDϵͳʹ����
* ��ʵ�û�id����ʹ�õ��ÿ��Թ�setuid����ʹ�á�
* ��ע��POSIX������ʹ����ʵ�û�ID����
* ��ע1��Ӣ��ע�Ϳ�ʼ�� 'XXX' ��ʾ��Ҫ��ʾ����
*/
//// ����ļ��ķ���Ȩ�ޡ�
// ����filename���ļ�����mode�Ǽ��ķ������ԣ�����3����Ч����λ��ɣ�R_OK(ֵ4)��
// W_OK(2)��X_OK(1) ��F_OK(0) ��ɣ��ֱ��ʾ����ļ��Ƿ�ɶ�����д����ִ�к��ļ���
// ����ڡ�������������Ļ�����0�����س����롣
48 int sys_access(const char * filename,int mode)
49 {
50 struct m_inode * inode;
51 int res, i_mode;
52
// �ļ��ķ���Ȩ����ϢҲͬ���������ļ���i�ڵ�ṹ�У��������Ҫ��ȡ�ö�Ӧ�ļ�����i
// �ڵ㡣���ķ�������mode�ɵ�3λ��ɣ������Ҫ���ϰ˽���0007��������и߱���λ��
// ����ļ�����Ӧ��i�ڵ㲻���ڣ���û������Ȩ�����롣��i�ڵ���ڣ���ȡi�ڵ�
// ���ļ������룬���Żظ�i�ڵ㡣���⣬57������䡰iput(inode);��������61��֮��
53 mode &= 0007;
54 if (!(inode=namei(filename)))
55 return -EACCES; // �����룺����Ȩ�ޡ�
56 i_mode = res = inode->i_mode & 0777;
57 iput(inode);
// �����ǰ�����û��Ǹ��ļ�����������ȡ�ļ��������ԡ����������ǰ�����û�����ļ���
// ��ͬ��һ�飬��ȡ�ļ������ԡ�����ʱres���3�����������˷��ʸ��ļ����������ԡ�
// [[?? ����Ӧres >>3 ??]
58 if (current->uid == inode->i_uid)
59 res >>= 6;
60 else if (current->gid == inode->i_gid)
61 res >>= 6;
// ��ʱres�����3�����Ǹ��ݵ�ǰ�����û����ļ��Ĺ�ϵѡ������ķ�������λ����������
// ���ж���3���ء�����ļ����Ծ��в�������ѯ������λmode����������ɣ�����0
62 if ((res & 0007 & mode) == mode)
63 return 0;
64 /*
65 * XXX we are doing this test last because we really should be
66 * swapping the effective with the real user id (temporarily),
67 * and then calling suser() routine. If we do call the
68 * suser() routine, it needs to be called last.
69 */
/*
* XXX ��������������IJ��ԣ���Ϊ����ʵ������Ҫ������Ч�û�ID��
* ��ʵ�û�ID����ʱ�أ���Ȼ��ŵ���suser()�������������ȷʵҪ����
* suser()����������Ҫ���ű����á�
*/
// �����ǰ�û�IDΪ0�������û�������������ִ��λ��0�����ļ����Ա��κ���ִ�С���
// ������0�����س����롣
70 if ((!current->uid) &&
71 (!(mode & 1) || (i_mode & 0111)))
72 return 0;
73 return -EACCES; // �����룺����Ȩ�ޡ�
74 }
75
//// �ı䵱ǰ����Ŀ¼ϵͳ���á�
// ����filename��Ŀ¼����
// �����ɹ���0�����س����롣
76 int sys_chdir(const char * filename)
77 {
78 struct m_inode * inode;
79
// �ı䵱ǰ����Ŀ¼����Ҫ��ѽ�������ṹ�ĵ�ǰ����Ŀ¼�ֶ�ָ�����Ŀ¼����i�ڵ㡣
// �����������ȡĿ¼����i�ڵ㡣���Ŀ¼����Ӧ��i�ڵ㲻���ڣ��س����롣�����
// i�ڵ㲻��һ��Ŀ¼i�ڵ㣬��Żظ�i�ڵ㣬�����س����롣
80 if (!(inode = namei(filename)))
81 return -ENOENT; // �����룺�ļ���Ŀ¼�����ڡ�
82 if (!S_ISDIR(inode->i_mode)) {
83 iput(inode);
84 return -ENOTDIR; // �����룺����Ŀ¼����
85 }
// Ȼ���ͷŽ���ԭ����Ŀ¼i�ڵ㣬��ʹ��ָ�������õĹ���Ŀ¼i�ڵ㡣����0��
86 iput(current->pwd);
87 current->pwd = inode;
88 return (0);
89 }
90
//// �ı��Ŀ¼ϵͳ���á�
// ��ָ����Ŀ¼�����ó�Ϊ��ǰ���̵ĸ�Ŀ¼'/'��
// ��������ɹ���0�����س����롣
91 int sys_chroot(const char * filename)
92 {
93 struct m_inode * inode;
94
// �õ������ڸı䵱ǰ��������ṹ�еĸ�Ŀ¼�ֶ�root������ָ���������Ŀ¼����i�ڵ㡣
// ���Ŀ¼����Ӧ��i�ڵ㲻���ڣ��س����롣�����i�ڵ㲻��Ŀ¼i�ڵ㣬��Żظ�
// i�ڵ㣬Ҳ���س����롣
95 if (!(inode=namei(filename)))
96 return -ENOENT;
97 if (!S_ISDIR(inode->i_mode)) {
98 iput(inode);
99 return -ENOTDIR;
100 }
// Ȼ���ͷŵ�ǰ���̵ĸ�Ŀ¼i�ڵ㣬����������Ϊָ��Ŀ¼����i�ڵ㣬����0��
101 iput(current->root);
102 current->root = inode;
103 return (0);
104 }
105
//// ���ļ�����ϵͳ���á�
// ����filename���ļ�����mode���µ��ļ����ԡ�
// �������ɹ���0�����س����롣
106 int sys_chmod(const char * filename,int mode)
107 {
108 struct m_inode * inode;
109
// �õ���Ϊָ���ļ������µķ�������mode���ļ��ķ����������ļ�����Ӧ��i�ڵ��У����
// ��������ȡ�ļ�����Ӧ��i�ڵ㡣���i�ڵ㲻���ڣ��س����루�ļ���Ŀ¼�����ڣ���
// �����ǰ���̵���Ч�û�id���ļ�i�ڵ���û�id��ͬ������Ҳ���dz����û�����Żظ�
// �ļ�i�ڵ㣬���س����루û�з���Ȩ�ޣ���
110 if (!(inode=namei(filename)))
111 return -ENOENT;
112 if ((current->euid != inode->i_uid) && !suser()) {
113 iput(inode);
114 return -EACCES;
115 }
// ������������ø�i�ڵ���ļ����ԣ����ø�i�ڵ����ı�־���Żظ�i�ڵ㣬����0��
116 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
117 inode->i_dirt = 1;
118 iput(inode);
119 return 0;
120 }
121
//// ���ļ�����ϵͳ���á�
// ����filename���ļ�����uid���û���ʶ��(�û�ID)��gid����ID��
// �������ɹ���0�����س����롣
122 int sys_chown(const char * filename,int uid,int gid)
123 {
124 struct m_inode * inode;
125
// �õ������������ļ�i�ڵ��е��û�����ID���������Ҫȡ�ø����ļ�����i�ڵ㡣�����
// ������i�ڵ㲻���ڣ��س����루�ļ���Ŀ¼�����ڣ��������ǰ���̲��dz����û���
// ��Żظ�i�ڵ㣬�����س����루û�з���Ȩ�ޣ���
126 if (!(inode=namei(filename)))
127 return -ENOENT;
128 if (!suser()) {
129 iput(inode);
130 return -EACCES;
131 }
// �������Ǿ��ò����ṩ��ֵ�������ļ�i�ڵ���û�ID����ID������i�ڵ��Ѿ��ı�־��
// �Żظ�i�ڵ㣬����0��
132 inode->i_uid=uid;
133 inode->i_gid=gid;
134 inode->i_dirt=1;
135 iput(inode);
136 return 0;
137 }
138
//// ����ַ��豸���͡�
// �ú��������������ļ���ϵͳ����sys_open()�����ڼ�������ļ���tty�ն��ַ���
// ��ʱ����Ҫ�Ե�ǰ���̵����úͶ�tty�������á�
// ����0�����ɹ�������-1��ʾʧ�ܣ���Ӧ�ַ��豸���ܴ�
139 static int check_char_dev(struct m_inode * inode, int dev, int flag)
140 {
141 struct tty_struct *tty;
142 int min; // ���豸�š�
143
// ֻ�������豸����4��/dev/ttyxx�ļ�����5��/dev/tty�ļ����������/dev/tty�����豸
// ����0�����һ�������п����նˣ������ǽ��̿����ն��豸��ͬ��������/dev/tty�豸��
// һ�������豸������Ӧ������ʵ��ʹ�õ�/dev/ttyxx�豸֮һ������һ��������˵��������
// �����նˣ���ô��������ṹ�е�tty�ֶν���4���豸��ijһ�����豸�š�
// ����������ļ��� /dev/tty����MAJOR(dev) = 5������ô������min = ��������ṹ
// �е�tty�ֶΣ���ȡ4���豸�����豸�š������������ij��4���豸����ֱ��ȡ����
// �豸�š�����õ��� 4���豸���豸��С��0����ô˵������û�п����նˣ������豸�Ŵ�
// ���� -1����ʾ���ڽ���û�п����նˣ����߲��ܴ�����豸��
144 if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
145 if (MAJOR(dev) == 5)
146 min = current->tty;
147 else
148 min = MINOR(dev);
149 if (min < 0)
150 return -1;
// ��α�ն��豸�ļ�ֻ�ܱ����̶�ռʹ�á�������豸�ű�����һ����α�նˣ����Ҹô��ļ�
// i �ڵ����ü������� 1����˵�����豸�ѱ���������ʹ�á���˲����ٴ��ַ��豸�ļ���
// ���Ƿ��� -1������������tty�ṹָ��ttyָ��tty���ж�Ӧ�ṹ������ļ�������
// ־flag�в�����������ն˱�־O_NOCTTY�����ҽ����ǽ��������죬���ҵ�ǰ����û�п���
// �նˣ�����tty�ṹ��session�ֶ�Ϊ0����ʾ���ն˻������κν�����Ŀ����նˣ�����ô
// ������Ϊ������������ն��豸 min Ϊ������նˡ��������ý�������ṹ�ն��豸���ֶ�
// ttyֵ����min���������ö�Ӧtty�ṹ�ĻỰ��session�ͽ������pgrp�ֱ���ڽ��̵Ļ�
// ���źͽ�����š�
151 if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
152 return -1;
153 tty = TTY_TABLE(min);
154 if (!(flag & O_NOCTTY) &&
155 current->leader &&
156 current->tty<0 &&
157 tty->session==0) {
158 current->tty = min;
159 tty->session= current->session;
160 tty->pgrp = current->pgrp;
161 }
// ������ļ�������־flag�к���O_NONBLOCK������������־����������Ҫ�Ը��ַ��ն�
// �豸����������ã�����Ϊ�����������Ҫ��ȡ�������ַ���Ϊ0�����ó�ʱ��ʱֵΪ0��
// �����ն��豸���óɷǹ淶ģʽ����������ʽֻ�ܹ����ڷǹ淶ģʽ���ڴ�ģʽ�µ�VMIN
// ��VTIME������Ϊ0ʱ�������������ж���֧�����̾Ͷ�ȡ�����ַ��������̷��ء��μ�
// include/termios.h�ļ����˵����
162 if (flag & O_NONBLOCK) {
163 TTY_TABLE(min)->termios.c_cc[VMIN] =0;
164 TTY_TABLE(min)->termios.c_cc[VTIME] =0;
165 TTY_TABLE(min)->termios.c_lflag &= ~ICANON;
166 }
167 }
168 return 0;
169 }
170
//// �������ļ�ϵͳ���á�
// ����filename���ļ�����flag�Ǵ��ļ���־������ȡֵ��O_RDONLY��ֻ������O_WRONLY
// ��ֻд����O_RDWR����д�����Լ�O_CREAT����������O_EXCL���������ļ����벻���ڣ���
// O_APPEND�����ļ�β�������ݣ�������һЩ��־����ϣ���������ô�����һ�����ļ�����
// mode������ָ���ļ����������ԡ���Щ������S_IRWXU���ļ��������ж���д��ִ��Ȩ�ޣ���
// S_IRUSR���û����ж��ļ�Ȩ�ޣ���S_IRWXG�����Ա���ж���д��ִ��Ȩ�ޣ��ȵȡ�������
// �������ļ�����Щ����ֻӦ���ڽ������ļ��ķ��ʣ�������ֻ���ļ��Ĵ���Ҳ������һ
// ���ɶ�д���ļ������������ò����ɹ������ļ����(�ļ�������)�����س����롣
// �μ�sys/stat.h��fcntl.h��
171 int sys_open(const char * filename,int flag,int mode)
172 {
173 struct m_inode * inode;
174 struct file * f;
175 int i,fd;
176
// ���ȶԲ������д��������û����õ��ļ�ģʽ�ͽ���ģʽ���������룬�������ɵ��ļ�ģʽ��
// Ϊ��Ϊ���ļ�����һ���ļ��������Ҫ�������̽ṹ���ļ��ṹָ�����飬�Բ���һ����
// ����������������fd���Ǿ��ֵ�����Ѿ�û�п�����س����루������Ч����
177 mode &= 0777 & ~current->umask;
178 for(fd=0 ; fd<NR_OPEN ; fd++)
179 if (!current->filp[fd]) // �ҵ������
180 break;
181 if (fd>=NR_OPEN)
182 return -EINVAL;
// Ȼ���������õ�ǰ���̵�ִ��ʱ�ر��ļ������close_on_exec��λͼ����λ��Ӧ�ı���λ��
// close_on_exec ��һ�����������ļ������λͼ��־��ÿ������λ����һ�����ŵ��ļ���
// ����������ȷ���ڵ���ϵͳ���� execve()ʱ��Ҫ�رյ��ļ������������ʹ�� fork()����
// ������һ���ӽ���ʱ��ͨ�����ڸ��ӽ����е���execve()��������ִ����һ���³���ʱ
// �ӽ����п�ʼִ���³�����һ���ļ������close_on_exec�еĶ�Ӧ����λ����λ����ô
// ��ִ��execve()ʱ�ö�Ӧ�ļ���������رգ�������ļ������ʼ�մ��ڴ�״̬������
// һ���ļ�ʱ��Ĭ��������ļ�������ӽ�����Ҳ���ڴ�״̬���������Ҫ��λ��Ӧ����λ��
// Ȼ��Ϊ���ļ����ļ�����Ѱ��һ�����нṹ�������fָ���ļ������鿪ʼ����������
// ���ļ��ṹ����ü���Ϊ0��������Ѿ�û�п����ļ����ṹ��س����롣���⣬
// ��184���ϵ�ָ�븳ֵ "0+file_table " ��ͬ�� "file_table" �� "&file_table[0]"��
// ��������д���ܸ�������һЩ��
183 current->close_on_exec &= ~(1<<fd);
184 f=0+file_table;
185 for (i=0 ; i<NR_FILE ; i++,f++)
186 if (!f->f_count) break;
187 if (i>=NR_FILE)
188 return -EINVAL;
// ��ʱ�����ý��̶�Ӧ�ļ����fd���ļ��ṹָ��ָ�����������ļ��ṹ�������ļ����ü���
// ����1��Ȼ����ú���open_namei()ִ�д�����������ֵС��0����˵�������������ͷ�
// �����뵽���ļ��ṹ�����س�����i�����ļ������ɹ�����inode���Ѵ��ļ���i�ڵ�
// ָ�롣
189 (current->filp[fd]=f)->f_count++;
190 if ((i=open_namei(filename,flag,mode,&inode))<0) {
191 current->filp[fd]=NULL;
192 f->f_count=0;
193 return i;
194 }
// �����Ѵ��ļ�i�ڵ�������ֶΣ����ǿ���֪���ļ������͡����ڲ�ͬ���͵��ļ�������
// ��Ҫ��һЩ�ر����� ��������ַ��豸�ļ�����ô���Ǿ�Ҫ����check_char_dev()
// ��������鵱ǰ�����Ƿ��ܴ�����ַ��豸�ļ��������������������0������ô��
// check_char_dev()�л���ݾ����ļ���־Ϊ�������ÿ����նˡ� �����������
// ʹ�ø��ַ��豸�ļ�����ô����ֻ���ͷ�����������ļ���;����Դ�����س����롣
195 /* ttys are somewhat special (ttyxx major==4, tty major==5) */
/* ttys��Щ���⣨ttyxx�����豸��==4��tty�����豸��==5��*/
196 if (S_ISCHR(inode->i_mode))
197 if (check_char_dev(inode,inode->i_zone[0],flag)) {
198 iput(inode);
199 current->filp[fd]=NULL;
200 f->f_count=0;
201 return -EAGAIN; // �����ţ���Դ��ʱ�����á�
202 }
// ������ǿ��豸�ļ���������Ƭ�Ƿ��������������������Ҫ�ø��ٻ������и��豸
// �����л����ʧЧ��
203 /* Likewise with block-devices: check for floppy_change */
/* ͬ�����ڿ��豸�ļ�����Ҫ�����Ƭ�Ƿ��� */
204 if (S_ISBLK(inode->i_mode))
205 check_disk_change(inode->i_zone[0]);
// �������dz�ʼ�����ļ����ļ��ṹ�������ļ��ṹ���Ժͱ�־���þ�����ü���Ϊ1����
// ����i�ڵ��ֶ�Ϊ���ļ���i�ڵ㣬��ʼ���ļ���дָ��Ϊ0������ļ�����š�
206 f->f_mode = inode->i_mode;
207 f->f_flags = flag;
208 f->f_count = 1;
209 f->f_inode = inode;
210 f->f_pos = 0;
211 return (fd);
212 }
213
//// �����ļ�ϵͳ���á�
// ����pathname��·������mode�������sys_open()������ͬ��
// �ɹ����ļ���������س����롣
214 int sys_creat(const char * pathname, int mode)
215 {
216 return sys_open(pathname, O_CREAT | O_TRUNC, mode);
217 }
218
// �ر��ļ�ϵͳ���á�
// ����fd��������
// �ɹ���0�����س����롣
219 int sys_close(unsigned int fd)
220 {
221 struct file * filp;
222
// ���ȼ�������Ч�ԡ����������ļ����ֵ���ڳ���ͬʱ�ܴ��ļ���NR_OPEN����
// �����루������Ч����Ȼ��λ���̵�ִ��ʱ�ر��ļ����λͼ��Ӧλ�������ļ������Ӧ
// ���ļ��ṹָ����NULL���س����롣
223 if (fd >= NR_OPEN)
224 return -EINVAL;
225 current->close_on_exec &= ~(1<<fd);
226 if (!(filp = current->filp[fd]))
227 return -EINVAL;
// �����ø��ļ�������ļ��ṹָ��ΪNULL�����ڹر��ļ�֮ǰ����Ӧ�ļ��ṹ�еľ������
// �����Ѿ�Ϊ0����˵���ں˳�����ͣ��������Ӧ�ļ��ṹ�����ü�����1����ʱ�������
// ��Ϊ0����˵����������������ʹ�ø��ļ������Ƿ���0���ɹ�����������ü����ѵ���0��
// ˵�����ļ��Ѿ�û�н������ã����ļ��ṹ�ѱ�Ϊ���С����ͷŸ��ļ�i�ڵ㣬����0��
228 current->filp[fd] = NULL;
229 if (filp->f_count == 0)
230 panic("Close: file count is 0");
231 if (--filp->f_count)
232 return (0);
233 iput(filp->f_inode);
234 return (0);
235 }
236
1 /*
2 * linux/fs/exec.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * #!-checking implemented by tytso.
9 */
/*
* #!��ʼ�Ľű�����ļ����벿������tytsoʵ�ֵġ�
*/
10
11 /*
12 * Demand-loading implemented 01.12.91 - no need to read anything but
13 * the header into memory. The inode of the executable is put into
14 * "current->executable", and page faults do the actual loading. Clean.
15 *
16 * Once more I can proudly say that linux stood up to being changed: it
17 * was less than 2 hours work to get demand-loading completely implemented.
18 */
/*
* ����ʱ����ʵ����1991.12.1 - ֻ�轫ִ���ļ�ͷ�������ڴ�����뽫����
* ִ���ļ������ؽ��ڴ档ִ���ļ���i�ڵ㱻���ڵ�ǰ���̵Ŀ�ִ���ֶ���
* "current->executable"��ҳ�쳣�����ִ���ļ���ʵ�ʼ��ز��������������
*
* �ҿ�����һ���Ժ���˵��linux�������ģ�ֻ���˲���2Сʱ�Ĺ���ʱ���
* ��ȫʵ����������ش�����
*/
19
20 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źŲ�������ԭ�͡�
21 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
22 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
23 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͷ��ų����ȡ�
24 #include <a.out.h> // a.outͷ�ļ���������a.outִ���ļ���ʽ��һЩ�ꡣ
25
26 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�
27 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
28 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
29 #include <linux/mm.h> // �ڴ����ͷ�ļ�������ҳ���С�����һЩҳ���ͷź���ԭ�͡�
30 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
31
32 extern int sys_exit(int exit_code); // �˳�����ϵͳ���á�
33 extern int sys_close(int fd); // �ر��ļ�ϵͳ���á�
34
35 /*
36 * MAX_ARG_PAGES defines the number of pages allocated for arguments
37 * and envelope for the new program. 32 should suffice, this gives
38 * a maximum env+arg of 128kB !
39 */
/*
* MAX_ARG_PAGES������Ϊ�³������ĸ������ͻ�������ʹ�õ�����ڴ�ҳ����
* 32ҳ�ڴ�Ӧ���㹻�ˣ���ʹ�û����Ͳ�����env+arg���ռ���ܺʹﵽ128kB!
*/
40 #define MAX_ARG_PAGES 32
41
//// ʹ�ÿ��ļ�ϵͳ���á�
// ������library - �������
// Ϊ����ѡ��һ�����ļ������滻���̵�ǰ���ļ�i�ڵ��ֶ�ֵΪ����ָ�����ļ�����i�ڵ�
// ָ�롣���libraryָ��Ϊ�գ���ѽ��̵�ǰ�Ŀ��ļ��ͷŵ���
// ���أ��ɹ�����0�����س����롣
42 int sys_uselib(const char * library)
43 {
44 struct m_inode * inode;
45 unsigned long base;
46
// �����жϵ�ǰ�����Ƿ���ͨ���̡�����ͨ���鿴��ǰ���̵Ŀռ䳤���������ġ���Ϊ��ͨ��
// �̵Ŀռ䳤�ȱ�����ΪTASK_SIZE��64MB�����������������ַ�ռ䳤�Ȳ�����TASK_SIZE
// �س����루��Ч������������ȡ���ļ�i�ڵ�inode�������ļ���ָ��գ�������inode
// ����NULL��
47 if (get_limit(0x17) != TASK_SIZE)
48 return -EINVAL;
49 if (library) {
50 if (!(inode=namei(library))) /* get library inode */
51 return -ENOENT; /* ȡ���ļ�i�ڵ� */
52 } else
53 inode = NULL;
54 /* we should check filetypes (headers etc), but we don't */
/* ����Ӧ�ü��һ���ļ����ͣ���ͷ����Ϣ�ȣ����������ǻ�û���������� */
// Ȼ��Żؽ���ԭ���ļ�i�ڵ㣬��Ԥ�ý��̿�i�ڵ��ֶ�Ϊ�ա�����ȡ�ý��̵Ŀ��������
// λ�ã����ͷ�ԭ������ҳ������ռ�õ��ڴ�ҳ�档����ý��̿�i�ڵ��ֶ�ָ���¿�i��
// �㣬������0���ɹ�����
55 iput(current->library);
56 current->library = NULL;
57 base = get_base(current->ldt[2]);
58 base += LIBRARY_OFFSET;
59 free_page_tables(base,LIBRARY_SIZE);
60 current->library = inode;
61 return 0;
62 }
63
64 /*
65 * create_tables() parses the env- and arg-strings in new user
66 * memory and creates the pointer tables from them, and puts their
67 * addresses on the "stack", returning the new stack pointer value.
68 */
/*
* create_tables()�������������ڴ��н������������Ͳ����ַ������ɴ�
* ����ָ������������ǵĵ�ַ�ŵ�"ջ"�ϣ�Ȼ����ջ��ָ��ֵ��
*/
//// ��������ջ�д��������ͻ�������ָ�����
// ������p -���ݶ��в����ͻ�����Ϣƫ��ָ�룻argc - ����������envc - ��������������
// ���أ�ջָ��ֵ��
69 static unsigned long * create_tables(char * p,int argc,int envc)
70 {
71 unsigned long *argv,*envp;
72 unsigned long * sp;
73
// ջָ������4�ֽڣ�1�ڣ�Ϊ�߽����Ѱַ�ģ������������ spΪ4��������ֵ����ʱsp
// λ�ڲ�����������ĩ�ˡ�Ȼ�������Ȱ�sp ���£��͵�ַ�����ƶ�����ջ�пճ���������
// ָ��ռ�õĿռ䣬���û�������ָ��envp ָ��ô�����ճ���һ��λ�������������һ
// ��NULLֵ������ָ���1��sp������ָ������ֽ�ֵ��4�ֽڣ����ٰ�sp�����ƶ����ճ�
// �����в���ָ��ռ�õĿռ䣬����argv ָ��ָ��ô���ͬ������մ���һ��λ�����ڴ��
// һ��NULLֵ����ʱspָ�����ָ������ʼ�������ǽ�����������ָ��envp�������в�
// ����ָ���Լ������в�������ֵ�ֱ�ѹ��ջ�С�
74 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
75 sp -= envc+1; // ��sp = sp - (envc+1);
76 envp = sp;
77 sp -= argc+1;
78 argv = sp;
79 put_fs_long((unsigned long)envp,--sp);
80 put_fs_long((unsigned long)argv,--sp);
81 put_fs_long((unsigned long)argc,--sp);
// �ٽ������и�����ָ��ͻ���������ָ��ֱ����ǰ��ճ�������Ӧ�ط������ֱ����һ
// ��NULLָ�롣
82 while (argc-->0) {
83 put_fs_long((unsigned long) p,argv++);
84 while (get_fs_byte(p++)) /* nothing */ ; // pָ��ָ����һ����������
85 }
86 put_fs_long(0,argv);
87 while (envc-->0) {
88 put_fs_long((unsigned long) p,envp++);
89 while (get_fs_byte(p++)) /* nothing */ ; // pָ��ָ����һ����������
90 }
91 put_fs_long(0,envp);
92 return sp; // ���ع���ĵ�ǰ��ջָ�롣
93 }
94
95 /*
96 * count() counts the number of arguments/envelopes
97 */
/*
* count()�������������в���/���������ĸ�����
*/
//// �������������
// ������argv - ����ָ�����飬���һ��ָ������NULL��
// ͳ�Ʋ���ָ��������ָ��ĸ��������ں�����������ָ���ָ������ã���μ�����
// kernel/sched.c�е�171��ǰ��ע�͡�
// ���أ�����������
98 static int count(char ** argv)
99 {
100 int i=0;
101 char ** tmp;
102
103 if (tmp = argv)
104 while (get_fs_long((unsigned long *) (tmp++)))
105 i++;
106
107 return i;
108 }
109
110 /*
111 * 'copy_string()' copies argument/envelope strings from user
112 * memory to free pages in kernel mem. These are in a format ready
113 * to be put directly into the top of new user memory.
114 *
115 * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
116 * whether the string and the string array are from user or kernel segments:
117 *
118 * from_kmem argv * argv **
119 * 0 user space user space
120 * 1 kernel space user space
121 * 2 kernel space kernel space
122 *
123 * We do this by playing games with the fs segment register. Since it
124 * it is expensive to load a segment register, we try to avoid calling
125 * set_fs() unless we absolutely have to.
126 */
/*
* 'copy_string()'�������û��ڴ�ռ俽������/�����ַ������ں˿���ҳ���С�
* ��Щ�Ѿ���ֱ�ӷŵ����û��ڴ��еĸ�ʽ��
*
* ��TYT(Tytso)��1991.11.24���ģ�������from_kmem�������ò���ָ����
* �ַ������ַ��������������û��λ����ں˶Ρ�
*
* from_kmem ָ��argv * �ַ��� argv **
* 0 �û��ռ� �û��ռ�
* 1 �ں˿ռ� �û��ռ�
* 2 �ں˿ռ� �ں˿ռ�
*
* ������ͨ�������fs�μĴ����������ġ����ڼ���һ���μĴ�������̫�ߣ�
* �������Ǿ����������set_fs()������ʵ�ڱ�Ҫ��
*/
//// ����ָ�������IJ����ַ����������ͻ����ռ��С�
// ������argc - �����ӵIJ���������argv - ����ָ�����飻page - �����ͻ����ռ�ҳ��ָ��
// ���顣p -�������ռ���ƫ��ָ�룬ʼ��ָ���Ѹ��ƴ���ͷ����from_kmem -�ַ�����Դ��־��
// �� do_execve()�����У�p��ʼ��Ϊָ�������(128kB)�ռ�����һ�����ִ��������ַ���
// ���Զ�ջ������ʽ���������и��ƴ�ŵġ���� pָ������Ÿ�����Ϣ�����Ӷ���С��
// ��ʼ��ָ������ַ�����ͷ�����ַ�����Դ��־from_kmemӦ����TYTΪ�˸�execve()����
// ִ�нű��ļ��Ĺ��ܶ��¼ӵIJ�������û�����нű��ļ��Ĺ���ʱ�����в����ַ���������
// �����ݿռ��С�
// ���أ������ͻ����ռ䵱ǰͷ��ָ�롣��������0��
127 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
128 unsigned long p, int from_kmem)
129 {
130 char *tmp, *pag;
131 int len, offset = 0;
132 unsigned long old_fs, new_fs;
133
// ����ȡ��ǰ�μĴ���ds��ָ���ں����ݶΣ���fsֵ���ֱ𱣴浽����new_fs��old_fs�С�
// ����ַ������ַ������飨ָ�룩�����ں˿ռ䣬������fs�μĴ���ָ���ں����ݶΡ�
134 if (!p)
135 return 0; /* bullet-proofing */ /* ƫ��ָ����֤ */
136 new_fs = get_ds();
137 old_fs = get_fs();
138 if (from_kmem==2) // ��������ָ�����ں˿ռ�������fsָ���ں˿ռ䡣
139 set_fs(new_fs);
// Ȼ��ѭ���������������������һ����������ʼ���ƣ����Ƶ�ָ��ƫ�Ƶ�ַ������ѭ���У�
// ����ȡ��Ҫ���Ƶĵ�ǰ�ַ���ָ�롣����ַ������û��ռ���ַ������飨�ַ���ָ�룩��
// �ں˿ռ䣬������fs�μĴ���ָ���ں����ݶΣ�ds���������ں����ݿռ���ȡ���ַ���ָ��
// tmp֮������ָ̻�fs�μĴ���ԭֵ��fs��ָ���û��ռ䣩����������fsֵ��ֱ�Ӵ�
// �û��ռ�ȡ�ַ���ָ�뵽tmp��
140 while (argc-- > 0) {
141 if (from_kmem == 1) // ����ָ�����ں˿ռ䣬��fsָ���ں˿ռ䡣
142 set_fs(new_fs);
143 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
144 panic("argc is wrong");
145 if (from_kmem == 1) // ����ָ�����ں˿ռ䣬��fsָ���û��ռ䡣
146 set_fs(old_fs);
// Ȼ����û��ռ�ȡ���ַ�����������ò����ַ�������len�� �˺�tmpָ����ַ���ĩ�ˡ�
// ������ַ������ȳ�����ʱ�����ͻ����ռ��л�ʣ��Ŀ��г��ȣ���ռ䲻���ˡ����ǻָ�
// fs�μĴ���ֵ��������ı�Ļ���������0��������Ϊ�����ͻ����ռ�����128KB������ͨ
// �������ܷ������������
147 len=0; /* remember zero-padding */
148 do { /* ����֪��������NULL�ֽڽ�β�� */
149 len++;
150 } while (get_fs_byte(tmp++));
151 if (p-len < 0) { /* this shouldn't happen - 128kB */
152 set_fs(old_fs); /* ���ᷢ��-��Ϊ��128kB�Ŀռ� */
153 return 0;
154 }
// ����������������ַ��ذ��ַ������Ƶ������ͻ����ռ�ĩ�˴�����ѭ�������ַ������ַ�
// �����У���������Ҫ�жϲ����ͻ����ռ�����Ӧλ�ô��Ƿ��Ѿ����ڴ�ҳ�档�����û�о�
// ��Ϊ������1ҳ�ڴ�ҳ�档ƫ����offset������Ϊ��һ��ҳ���еĵ�ǰָ��ƫ��ֵ�� ��Ϊ
// �տ�ʼִ�б�����ʱ��ƫ�Ʊ���offset����ʼ��Ϊ0������(offset-1 < 0)�϶�������ʹ��
// offset���±�����Ϊ��ǰpָ����ҳ�淶Χ�ڵ�ƫ��ֵ��
155 while (len) {
156 --p; --tmp; --len;
157 if (--offset < 0) {
158 offset = p % PAGE_SIZE;
159 if (from_kmem==2) // �������ں˿ռ���fsָ���û��ռ䡣
160 set_fs(old_fs);
// �����ǰƫ��ֵp���ڵĴ��ռ�ҳ��ָ�������� page[p/PAGE_SIZE] ==0����ʾ��ʱpָ��
// �����Ŀռ��ڴ�ҳ�滹�����ڣ���������һ�����ڴ�ҳ��������ҳ��ָ������ָ�����飬ͬ
// ʱҲʹҳ��ָ��pagָ�����ҳ�档�����벻������ҳ����0��
161 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
162 !(pag = (char *) page[p/PAGE_SIZE] =
163 (unsigned long *) get_free_page()))
164 return 0;
165 if (from_kmem==2) // �������ں˿ռ���fsָ���ں˿ռ䡣
166 set_fs(new_fs);
167
168 }
// Ȼ���fs���и����ַ�����1�ֽڵ������ͻ����ռ��ڴ�ҳ��pag��offset����
169 *(pag + offset) = get_fs_byte(tmp);
170 }
171 }
// ����ַ������ַ����������ں˿ռ䣬��ָ�fs�μĴ���ԭֵ������ز����ͻ�����
// �����Ѹ��Ʋ�����ͷ��ƫ��ֵ��
172 if (from_kmem==2)
173 set_fs(old_fs);
174 return p;
175 }
176
//// ������ľֲ������������ݡ�
// �ľֲ���������LDT���������Ķλ�ַ�Ͷ��������������ͻ����ռ�ҳ����������ݶ�
// ĩ�ˡ�
// ������text_size - ִ���ļ�ͷ����a_text�ֶθ����Ĵ���γ���ֵ��
// page - �����ͻ����ռ�ҳ��ָ�����顣
// ���أ����ݶ���ֵ��64MB����
177 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
178 {
179 unsigned long code_limit,data_limit,code_base,data_base;
180 int i;
181
// ���ȰѴ�������ݶγ��Ⱦ�����Ϊ64MB�� Ȼ��ȡ��ǰ���ֲ̾���������������������д�
// ��λ�ַ������λ�ַ�����ݶλ�ַ��ͬ����ʹ����Щ��ֵ�������þֲ����д���κ�����
// ���������еĻ�ַ�Ͷ�����������ע�⣬���ڱ����ص��³���Ĵ�������ݶλ�ַ��ԭ��
// �����ͬ�����û�б�Ҫ���ظ�ȥ�������ǣ�����186��188���ϵ��������öλ�ַ�����
// ���࣬��ʡ�ԡ�
182 code_limit = TASK_SIZE;
183 data_limit = TASK_SIZE;
184 code_base = get_base(current->ldt[1]); // include/linux/sched.h����226��
185 data_base = code_base;
186 set_base(current->ldt[1],code_base);
187 set_limit(current->ldt[1],code_limit);
188 set_base(current->ldt[2],data_base);
189 set_limit(current->ldt[2],data_limit);
190 /* make sure fs points to the NEW data segment */
/* Ҫȷ��fs�μĴ�����ָ���µ����ݶ� */
// fs�μĴ����з���ֲ������ݶ���������ѡ���(0x17)����Ĭ�������fs��ָ���������ݶΡ�
191 __asm__("pushl $0x17\n\tpop %%fs"::);
// Ȼ�����ͻ����ռ��Ѵ�����ݵ�ҳ�棨�����MAX_ARG_PAGESҳ��128kB���ŵ����ݶ�ĩ
// �ˡ� �����Ǵӽ��̿ռ�����λ�ÿ�ʼ������һҳһҳ�طš����ļ�����ռ�ý��̿ռ����
// 4MB������put_dirty_page()���ڰ�����ҳ��ӳ�䵽�������ռ��С���mm/memory.c�С�
192 data_base += data_limit - LIBRARY_SIZE;
193 for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
194 data_base -= PAGE_SIZE;
195 if (page[i]) // ����ҳ����ڣ��ͷ��ø�ҳ�档
196 put_dirty_page(page[i],data_base);
197 }
198 return data_limit; // ������ݶ�����64MB����
199 }
200
201 /*
202 * 'do_execve()' executes a new program.
203 *
204 * NOTE! We leave 4MB free at the top of the data-area for a loadable
205 * library.
206 */
/*
* 'do_execve()'����ִ��һ���³���
*/
//// execve()ϵͳ�жϵ��ú��������ز�ִ���ӽ��̣���������
// �ú�����ϵͳ�жϵ��ã�int 0x80�����ܺ�__NR_execve���õĺ����������IJ����ǽ���ϵͳ
// ���ô������̺�ֱ�����ñ�ϵͳ���ô������̣�system_call.s��200�У��͵��ñ�����֮ǰ
// ��system_call.s����203�У���ѹ��ջ�е�ֵ����Щֵ������
// �� ��86--88����ѵ�edx��ecx��ebx�Ĵ���ֵ���ֱ��Ӧ**envp��**argv��*filename��
// �� ��94�е���sys_call_table��sys_execve������ָ�룩ʱѹ��ջ�ĺ������ص�ַ��tmp����
// �� ��202���ڵ��ñ�����do_execveǰ��ջ��ָ��ջ�е���ϵͳ�жϵij������ָ��eip��
// ������
// eip - ����ϵͳ�жϵij������ָ�룬�μ�kernel/system_call.s����ʼ���ֵ�˵����
// tmp - ϵͳ�ж����ڵ���_sys_execveʱ�ķ��ص�ַ�����ã�
// filename - ��ִ�г����ļ���ָ�룻
// argv - �����в���ָ�������ָ�룻
// envp - ��������ָ�������ָ�롣
// ���أ�������óɹ������أ��������ó����ţ�������-1��
207 int do_execve(unsigned long * eip,long tmp,char * filename,
208 char ** argv, char ** envp)
209 {
210 struct m_inode * inode;
211 struct buffer_head * bh;
212 struct exec ex;
213 unsigned long page[MAX_ARG_PAGES]; // �����ͻ������ռ�ҳ��ָ�����顣
214 int i,argc,envc;
215 int e_uid, e_gid; // ��Ч�û�ID����Ч��ID��
216 int retval;
217 int sh_bang = 0; // �����Ƿ���Ҫִ�нű�����
218 unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4; // pָ������ͻ����ռ�����
219
// ����ʽ����ִ���ļ������л���֮ǰ���������ȸ�Щ���¡��ں�����128KB��32��ҳ�棩
// �ռ�����Ż�ִ���ļ��������в����ͻ����ַ��������а�p��ʼ���ó�λ��128KB�ռ��
// ���1�����ִ����ڳ�ʼ�����ͻ����ռ�IJ��������У�p������ָ����128KB�ռ��еĵ�
// ǰλ�á�
// ���⣬����eip[1]�ǵ��ñ���ϵͳ���õ�ԭ�û��������μĴ���CSֵ�����еĶ�ѡ���
// ��Ȼ�����ǵ�ǰ����Ĵ����ѡ�����0x000f���������Ǹ�ֵ����ô CSֻ�ܻ����ں˴���
// �ε�ѡ��� 0x0008�� �����Ǿ��Բ������ģ���Ϊ�ں˴����dz�פ�ڴ�����ܱ��滻���ġ�
// ����������eip[1] ��ֵȷ���Ƿ�������������Ȼ���ٳ�ʼ��128KB�IJ����ͻ�������
// �䣬�������ֽ����㣬��ȡ��ִ���ļ���i�ڵ㡣�ٸ��ݺ��������ֱ����������в�����
// �����ַ����ĸ���argc��envc�����⣬ִ���ļ������dz����ļ���
220 if ((0xffff & eip[1]) != 0x000f)
221 panic("execve called from supervisor mode");
222 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
223 page[i]=0;
224 if (!(inode=namei(filename))) /* get executables inode */
225 return -ENOENT;
226 argc = count(argv); // �������������
227 envc = count(envp); // �����ַ�������������
228
229 restart_interp:
230 if (!S_ISREG(inode->i_mode)) { /* must be regular file */
231 retval = -EACCES;
232 goto exec_error2; //�����dz����ļ����ó����룬��ת��376�С�
233 }
// �����鵱ǰ�����Ƿ���Ȩ����ָ����ִ���ļ���������ִ���ļ�i�ڵ��е����ԣ�������
// �����Ƿ���Ȩִ�������ڰ�ִ���ļ�i�ڵ�������ֶ�ֵȡ��i�к��������Ȳ鿴������
// �Ƿ������ˡ�����-�û�-ID����set-user_id����־ �͡�����-��-ID����set-group-id����
// ־����������־��Ҫ����һ���û��ܹ�ִ����Ȩ�û����糬���û�root���ij�������ı�
// ����ij���passwd�ȡ����set-user-id��־��λ�������ִ�н��̵���Ч�û�ID��euid��
// �����ó�ִ���ļ����û�ID���������óɵ�ǰ���̵�euid�����ִ���ļ�set-group-id��
// ��λ�Ļ�����ִ�н��̵���Ч��ID��egid��������Ϊִ���ļ�����ID���������óɵ�ǰ����
// ��egid��������ʱ���������жϳ�����ֵ�����ڱ���e_uid��e_gid�С�
234 i = inode->i_mode;
235 e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
236 e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
// ���ڸ��ݽ��̵�euid��egid��ִ���ļ��ķ������Խ��бȽϡ����ִ���ļ��������н���
// ���û�������ļ�����ֵi����6λ����ʱ�����3λ���ļ������ķ���Ȩ�ޱ�־�������
// �����ִ���ļ��뵱ǰ���̵��û�����ͬ�飬��ʹ����ֵ���3λ��ִ���ļ����û��ķ���
// Ȩ�ޱ�־�������ʱ���������3λ���������û����ʸ�ִ���ļ���Ȩ�ޡ�
// Ȼ�����Ǹ���������i�����3����ֵ���жϵ�ǰ�����Ƿ���Ȩ���������ִ���ļ������
// ѡ������Ӧ�û�û�����и��ļ���Ȩ����λ0��ִ��Ȩ�ޣ������������û�Ҳû���κ�Ȩ��
// ���ߵ�ǰ�����û����dz����û����������ǰ����û��Ȩ���������ִ���ļ��������ò���
// ִ�г����룬����ת��exec_error2��ȥ���˳�������
237 if (current->euid == inode->i_uid)
238 i >>= 6;
239 else if (in_group_p(inode->i_gid))
240 i >>= 3;
241 if (!(i & 1) &&
242 !((inode->i_mode & 0111) && suser())) {
243 retval = -ENOEXEC;
244 goto exec_error2;
245 }
// ����ִ�е����˵����ǰ����������ָ��ִ���ļ���Ȩ�ޡ���˴����↑ʼ������Ҫȡ��
// ִ���ļ�ͷ�����ݲ��������е���Ϣ�������������л���������������һ��shell������ִ
// �нű��������ȶ�ȡִ���ļ���1�����ݵ����ٻ�����С� �����ƻ�������ݵ�ex�С�
// ���ִ���ļ���ʼ�������ֽ����ַ�'#!'����˵��ִ���ļ���һ���ű��ı��ļ����������
// �нű��ļ������Ǿ���Ҫִ�нű��ļ��Ľ��ͳ�������shell����ͨ���ű��ļ��ĵ�
// һ���ı�Ϊ��#��/bin/bash������ָ�������нű��ļ���Ҫ�Ľ��ͳ������з����Ǵӽű�
// �ļ���1�У����ַ�'#!'����ȡ�����еĽ��ͳ�����������IJ��������еĻ�����Ȼ����
// Щ�����ͽű��ļ����Ž�ִ���ļ�����ʱ�ǽ��ͳ��������в����ռ��С�����֮ǰ����
// ��Ȼ��Ҫ�ȰѺ���ָ����ԭ�������в����ͻ����ַ����ŵ�128KB�ռ��У������ィ������
// �������в�����ŵ�����ǰ��λ�ô�����Ϊ��������ã���������ں�ִ�нű��ļ��Ľ���
// ����������������úý��ͳ���Ľű��ļ����Ȳ�����ȡ�����ͳ����i�ڵ㲢��ת��
// 229��ȥִ�н��ͳ�������������Ҫ��ת��ִ�й��Ĵ���229��ȥ�����������ȷ�ϲ���
// ���˽ű��ļ�֮����Ҫ����һ����ֹ�ٴ�ִ������Ľű����������־sh_bang ���ں����
// �����иñ�־Ҳ������ʾ�����Ѿ����ú�ִ���ļ��������в�������Ҫ�ظ����á�
246 if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
247 retval = -EACCES;
248 goto exec_error2;
249 }
250 ex = *((struct exec *) bh->b_data); /* read exec-header */
251 if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
252 /*
253 * This section does the #! interpretation.
254 * Sorta complicated, but hopefully it will work. -TYT
255 */
/*
* �ⲿ�ִ�����'#!'�Ľ��ͣ���Щ���ӣ���ϣ���ܹ�����-TYT
*/
256
257 char buf[128], *cp, *interp, *i_name, *i_arg;
258 unsigned long old_fs;
259
// �����↑ʼ�����Ǵӽű��ļ�����ȡ���ͳ�����������������ѽ��ͳ����������ͳ���IJ���
// �ͽű��ļ�����Ϸ��뻷���������С����ȸ��ƽű��ļ�ͷ1���ַ�'#!'������ַ�����buf
// �У����к��нű����ͳ�����������/bin/sh����Ҳ���ܻ��������ͳ���ļ���������Ȼ���
// buf�е����ݽ��д�����ɾ����ʼ�Ŀո��Ʊ�����
260 strncpy(buf, bh->b_data+2, 127);
261 brelse(bh);
262 iput(inode); // �ͷŻ���鲢�Żؽű��ļ�i�ڵ㡣
263 buf[127] = '\0';
264 if (cp = strchr(buf, '\n')) {
265 *cp = '\0'; // ��1�����з�����NULL��ȥ���ո��Ʊ�����
266 for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
267 }
268 if (!cp || *cp == '\0') { // ������û���������ݣ��������
269 retval = -ENOEXEC; /* No interpreter name found */
270 goto exec_error1; /* û���ҵ��ű����ͳ����� */
271 }
// ��ʱ���ǵõ��˿�ͷ�ǽű����ͳ�������һ�����ݣ��ַ�����������������С�����ȡ��һ��
// �ַ�������Ӧ���ǽ��ͳ���������ʱi_nameָ������ơ������ͳ����������ַ���������Ӧ
// ���ǽ��ͳ���IJ�������������i_argָ��ô���
272 interp = i_name = cp;
273 i_arg = 0;
274 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
275 if (*cp == '/')
276 i_name = cp+1;
277 }
278 if (*cp) {
279 *cp++ = '\0'; // ���ͳ�����β����NULL�ַ���
280 i_arg = cp; // i_argָ����ͳ��������
281 }
282 /*
283 * OK, we've parsed out the interpreter name and
284 * (optional) argument.
285 */
/*
* OK�������Ѿ����������ͳ�����ļ����Լ�(��ѡ��)������
*/
// ��������Ҫ��������������Ľ��ͳ�����i_name �������i_arg �ͽű��ļ�����Ϊ���ͳ�
// ��IJ����Ž������Ͳ������С���������������Ҫ�Ѻ����ṩ��ԭ��һЩ�����ͻ����ַ���
// �ȷŽ�ȥ��Ȼ���ٷ�������������ġ�������������в�����˵�����ԭ���IJ�����"-arg1
// -arg2"�����ͳ�������"bash"���������"-iarg1 -iarg2"���ű��ļ�������ԭ����ִ����
// ��������"example.sh"����ô�ڷ�������IJ���֮���µ�������������������
// ��bash -iarg1 -iarg2 example.sh -arg1 -arg2��
// �������ǰ�sh_bang��־���ϣ�Ȼ��Ѻ��������ṩ��ԭ�в����ͻ����ַ������뵽�ռ��С�
// �����ַ����Ͳ��������ֱ���envc ��argc-1�����ٸ��Ƶ�һ��ԭ�в�����ԭ����ִ���ļ�
// ����������Ľű��ļ�����[[?? ���Կ�����ʵ�������Dz���Ҫȥ���д����ű��ļ���������
// ����ȫ���Ը���argc������������ԭ��ִ���ļ����������ڵĽű��ļ���������Ϊ��λ��ͬ
// һ��λ���� ]]��ע�⣡����ָ��p���Ÿ�����Ϣ���Ӷ�����С��ַ�����ƶ������������
// ���ƴ�����ִ���������������Ϣ��λ�ڳ��������в�������Ϣ����Ϸ������� pָ��
// ����ĵ�1����������copy_strings()���һ��������0��ָ�������ַ������û��ռ䡣
286 if (sh_bang++ == 0) {
287 p = copy_strings(envc, envp, page, p, 0);
288 p = copy_strings(--argc, argv+1, page, p, 0);
289 }
290 /*
291 * Splice in (1) the interpreter's name for argv[0]
292 * (2) (optional) argument to interpreter
293 * (3) filename of shell script
294 *
295 * This is done in reverse order, because of how the
296 * user environment and arguments are stored.
297 */
/*
* ƴ�� (1) argv[0]�зŽ��ͳ��������
* (2) (��ѡ��)���ͳ���IJ���
* (3) �ű����������
*
* ������������д����ģ��������û������Ͳ����Ĵ�ŷ�ʽ��ɵġ�
*/
// �������������ƽű��ļ��������ͳ���IJ����ͽ��ͳ����ļ����������ͻ����ռ��С�
// �����������ó����룬��ת��exec_error1�����⣬���ڱ����������ṩ�Ľű��ļ���
// filename���û��ռ䣬�����︳��copy_strings()�Ľű��ļ�����ָ�����ں˿ռ䣬��
// ����������ַ������������һ���������ַ�����Դ��־����Ҫ�����ó�1�����ַ�����
// �ں˿ռ䣬��copy_strings()�����һ������Ҫ���ó�2��������ĵ�301��304�С�
298 p = copy_strings(1, &filename, page, p, 1);
299 argc++;
300 if (i_arg) { // ���ƽ��ͳ���Ķ��������
301 p = copy_strings(1, &i_arg, page, p, 2);
302 argc++;
303 }
304 p = copy_strings(1, &i_name, page, p, 2);
305 argc++;
306 if (!p) {
307 retval = -ENOMEM;
308 goto exec_error1;
309 }
310 /*
311 * OK, now restart the process with the interpreter's inode.
312 */
/*
* OK������ʹ�ý��ͳ����i�ڵ��������̡�
*/
// �������ȡ�ý��ͳ����i�ڵ�ָ�룬Ȼ����ת��204��ȥִ�н��ͳ���Ϊ�˻�ý��ͳ�
// ���i�ڵ㣬������Ҫʹ��namei()���������Ǹú�����ʹ�õIJ������ļ������Ǵ��û���
// �ݿռ�õ��ģ����ӶμĴ���fs��ָ�ռ���ȡ�á�����ڵ���namei()����֮ǰ������Ҫ
// ����ʱ��fsָ���ں����ݿռ䣬���ú����ܴ��ں˿ռ�õ����ͳ�����������namei()
// ���غ�ָ�fs��Ĭ�����á����������������ʱ����ԭfs�μĴ�����ԭָ���û����ݶΣ�
// ��ֵ���������ó�ָ���ں����ݶΣ�Ȼ��ȡ���ͳ����i�ڵ㡣֮���ٻָ�fs��ԭֵ����
// ��ת��restart_interp��204�У������´����µ�ִ���ļ� -- �ű��ļ��Ľ��ͳ���
313 old_fs = get_fs();
314 set_fs(get_ds());
315 if (!(inode=namei(interp))) { /* get executables inode */
316 set_fs(old_fs); /* ȡ�ý��ͳ����i�ڵ� */
317 retval = -ENOENT;
318 goto exec_error1;
319 }
320 set_fs(old_fs);
321 goto restart_interp;
322 }
// ��ʱ������е�ִ���ļ�ͷ�ṹ�����Ѿ����Ƶ���ex �С� �������ͷŸû���飬����ʼ��
// ex�е�ִ��ͷ��Ϣ�����жϴ���������Linux 0.12�ں���˵������֧��ZMAGICִ���ļ���
// ʽ������ִ���ļ����붼������ַ0 ��ʼִ�У���˲�֧�ֺ��д���������ض�λ��Ϣ��
// ִ���ļ�����Ȼ�����ִ���ļ�ʵ��̫�����ִ���ļ���ȱ��ȫ����ô����Ҳ������������
// ��˶��������������ִ�г������ִ���ļ���������ҳ��ִ���ļ���ZMAGIC�������ߴ�
// ��������ض�λ���ֳ��Ȳ�����0������(�����+���ݶ�+��) ���ȳ���50MB������ִ���ļ�
// ����С�� (�����+���ݶ�+���ű�����+ִ��ͷ����) ���ȵ��ܺ͡�
323 brelse(bh);
324 if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
325 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
326 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
327 retval = -ENOEXEC;
328 goto exec_error2;
329 }
// ���⣬���ִ���ļ��д��뿪ʼ��û��λ��1��ҳ�棨1024�ֽڣ��߽紦����Ҳ����ִ�С�
// ��Ϊ����ҳ��Demand paging������Ҫ�����ִ���ļ�����ʱ��ҳ��Ϊ��λ�����Ҫ��ִ��
// �ļ�ӳ���д�������ݶ���ҳ��߽紦��ʼ��
330 if (N_TXTOFF(ex) != BLOCK_SIZE) {
331 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
332 retval = -ENOEXEC;
333 goto exec_error2;
334 }
// ���sh_bang��־û�����ã�����ָ�������������в����ͻ����ַ����������ͻ����ռ�
// �С���sh_bang��־�Ѿ����ã�������ǽ����нű����ͳ���ʱ��������ҳ���Ѿ����ƣ�
// �����ٸ��ơ�ͬ������sh_bangû����λ����Ҫ���ƵĻ�����ô��ʱָ��p���Ÿ�����Ϣ��
// �Ӷ�����С��ַ�����ƶ���������������ƴ�����ִ���������������Ϣ��λ�ڳ���
// ��������Ϣ����Ϸ�������pָ�����ĵ�1������������ʵ�ϣ�p��128KB�����ͻ�����
// ���е�ƫ��ֵ��������p=0�����ʾ��������������ռ�ҳ���Ѿ���ռ�������ɲ����ˡ�
335 if (!sh_bang) {
336 p = copy_strings(envc,envp,page,p,0);
337 p = copy_strings(argc,argv,page,p,0);
338 if (!p) {
339 retval = -ENOMEM;
340 goto exec_error2;
341 }
342 }
343 /* OK, This is the point of no return */
344 /* note that current->library stays unchanged by an exec */
/* OK�����濪ʼ��û�з��صĵط��� */
// ǰ��������Ժ��������ṩ����Ϣ����Ҫ����ִ���ļ��������в����ͻ����ռ���������ã�
// ����û��Ϊִ���ļ�����ʲôʵ���ԵĹ���������û������Ϊִ���ļ���ʼ����������ṹ
// ��Ϣ������ҳ���ȹ������������Ǿ�������Щ����������ִ���ļ�ֱ��ʹ�õ�ǰ���̵ġ���
// �ǡ�������ǰ���̽��������ִ���ļ��Ľ��̣����������Ҫ�����ͷŵ�ǰ����ռ�õ�ijЩ
// ϵͳ��Դ�������ر�ָ�����Ѵ��ļ���ռ�õ�ҳ�����ڴ�ҳ��ȡ�Ȼ�����ִ���ļ�ͷ��
// ����Ϣ�ĵ�ǰ����ʹ�õľֲ���������LDT�������������ݣ��������ô���κ����ݶ���
// ����������������ǰ�洦���õ���e_uid��e_gid����Ϣ�����ý�������ṹ����ص���
// �Ρ�����ִ�б���ϵͳ���ó���ķ��ص�ַ eip[]ָ��ִ���ļ��д������ʼλ�ô�����
// ������ϵͳ�����˳����غ�ͻ�ȥ������ִ���ļ��Ĵ����ˡ�ע�⣬��Ȼ��ʱ��ִ���ļ���
// ������ݻ�û�д��ļ��м��ص��ڴ��У���������ͻ������Ѿ���copy_strings() ��ʹ��
// get_free_page()�����������ڴ�ҳ���������ݣ�����change_ldt()������ʹ��put_page()
// ���˽������ռ��ĩ�˴������⣬��create_tables()��Ҳ���������û�ջ�ϴ�Ų���
// �ͻ���ָ���������ȱҳ�쳣���Ӷ��ڴ��������Ҳ��ʹ�Ϊ�û�ջ�ռ�ӳ�������ڴ�ҳ��
//
// �����������ȷŻؽ���ԭִ�г����i�ڵ㣬�����ý���executable �ֶ�ָ����ִ���ļ�
// ��i�ڵ㡣Ȼ��λԭ���̵������źŴ��������������SIG_IGN������븴λ���ٸ�����
// ����ִ��ʱ�ر��ļ������close_on_exec��λͼ��־���ر�ָ���Ĵ��ļ�����λ�ñ�־��
345 if (current->executable)
346 iput(current->executable);
347 current->executable = inode;
348 current->signal = 0;
349 for (i=0 ; i<32 ; i++) {
350 current->sigaction[i].sa_mask = 0;
351 current->sigaction[i].sa_flags = 0;
352 if (current->sigaction[i].sa_handler != SIG_IGN)
353 current->sigaction[i].sa_handler = NULL;
354 }
355 for (i=0 ; i<NR_OPEN ; i++)
356 if ((current->close_on_exec>>i)&1)
357 sys_close(i);
358 current->close_on_exec = 0;
// Ȼ����ݵ�ǰ����ָ���Ļ���ַ�������ͷ�ԭ������Ĵ���κ����ݶ�����Ӧ���ڴ�ҳ��
// ָ���������ڴ�ҳ�漰ҳ����������ʱ��ִ���ļ���û��ռ�����ڴ����κ�ҳ�棬����ڴ�
// ��������������ִ���ļ�����ʱ�ͻ�����ȱҳ�쳣�жϣ���ʱ�ڴ��������ִ��ȱҳ��
// ����Ϊ��ִ���ļ������ڴ�ҳ����������ҳ������Ұ����ִ���ļ�ҳ������ڴ��С�
// ������ϴ�����ʹ����Э��������ָ����ǵ�ǰ���̣������ÿգ�����λʹ����Э������
// �ı�־��
359 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
360 free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
361 if (last_task_used_math == current)
362 last_task_used_math = NULL;
363 current->used_math = 0;
// Ȼ�����Ǹ�����ִ���ļ�ͷ�ṹ�еĴ��볤���ֶ� a_text ��ֵ�ľֲ�������������ַ��
// ����������128KB �IJ����ͻ����ռ�ҳ����������ݶ�ĩ�ˡ�ִ���������֮��p��ʱ
// ���ij������ݶ���ʼ��Ϊԭ���ƫ��ֵ������ָ������ͻ����ռ����ݿ�ʼ��������ת����
// Ϊջָ��ֵ��Ȼ������ڲ�����create_tables() ��ջ�ռ��д��������Ͳ�������ָ�����
// �������main()��Ϊ����ʹ�ã������ظ�ջָ�롣
364 p += change_ldt(ex.a_text,page);
365 p -= LIBRARY_SIZE + MAX_ARG_PAGES*PAGE_SIZE;
366 p = (unsigned long) create_tables((char *)p,argc,envc);
// �������Ľ��̸��ֶ�ֵΪ��ִ���ļ�����Ϣ�������������ṹ����β�ֶ�end_code��
// ��ִ���ļ��Ĵ���γ��� a_text������β�ֶ� end_data ����ִ���ļ��Ĵ���γ��ȼ���
// �ݶγ��ȣ�a_data + a_text����������̶ѽ�β�ֶ�brk = a_text + a_data + a_bss��
// brk����ָ�����̵�ǰ���ݶΣ�����δ��ʼ�����ݲ��֣�ĩ��λ�ã����ں�Ϊ���̷����ڴ�
// ʱָ�����俪ʼλ�á�Ȼ�����ý���ջ��ʼ�ֶ�Ϊջָ������ҳ�棬���������ý��̵���Ч
// �û�id����Ч��id��
367 current->brk = ex.a_bss +
368 (current->end_data = ex.a_data +
369 (current->end_code = ex.a_text));
370 current->start_stack = p & 0xfffff000;
371 current->suid = current->euid = e_uid;
372 current->sgid = current->egid = e_gid;
// ���ԭ����ϵͳ�жϵij����ڶ�ջ�ϵĴ���ָ���滻Ϊָ����ִ�г������ڵ㣬����ջ
// ָ���滻Ϊ��ִ���ļ���ջָ�롣�˺�ָ�������Щջ���ݲ�ʹ��CPUȥִ����ִ��
// �ļ�����˲��᷵�ص�ԭ����ϵͳ�жϵij�����ȥ�ˡ�
373 eip[0] = ex.a_entry; /* eip, magic happens :-) */ /* eip��ħ����������*/
374 eip[3] = p; /* stack pointer */ /* esp����ջָ�� */
375 return 0;
376 exec_error2:
377 iput(inode); // �Ż�i�ڵ㡣
378 exec_error1:
379 for (i=0 ; i<MAX_ARG_PAGES ; i++)
380 free_page(page[i]); // �ͷŴ�Ų����ͻ��������ڴ�ҳ�档
381 return(retval); // ���س����롣
382 }
383
1 /*
2 * linux/fs/stat.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
8 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͳ�����
9
10 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ��������ļ����ṹ��file��m_inode���ȡ�
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14
//// �����ļ�״̬��Ϣ��
// ����inode���ļ�i�ڵ㣬statbuf���û����ݿռ���stat�ļ�״̬�ṹָ�룬���ڴ��ȡ
// �õ�״̬��Ϣ��
15 static void cp_stat(struct m_inode * inode, struct stat * statbuf)
16 {
17 struct stat tmp;
18 int i;
19
// ������֤(�����)������ݵ��ڴ�ռ䡣Ȼ����ʱ������Ӧ�ڵ��ϵ���Ϣ��
20 verify_area(statbuf,sizeof (struct stat));
21 tmp.st_dev = inode->i_dev; // �ļ����ڵ��豸�š�
22 tmp.st_ino = inode->i_num; // �ļ�i�ڵ�š�
23 tmp.st_mode = inode->i_mode; // �ļ����ԡ�
24 tmp.st_nlink = inode->i_nlinks; // ���������
25 tmp.st_uid = inode->i_uid; // �ļ����û�ID��
26 tmp.st_gid = inode->i_gid; // �����ID��
27 tmp.st_rdev = inode->i_zone[0]; // �豸�ţ����������ַ��ļ�����豸�ļ�����
28 tmp.st_size = inode->i_size; // �ļ��ֽڳ��ȣ�����ļ��dz����ļ�����
29 tmp.st_atime = inode->i_atime; // ������ʱ�䡣
30 tmp.st_mtime = inode->i_mtime; // �����ʱ�䡣
31 tmp.st_ctime = inode->i_ctime; // ���i�ڵ���ʱ�䡣
// �����Щ״̬��Ϣ���Ƶ��û��������С�
32 for (i=0 ; i<sizeof (tmp) ; i++)
33 put_fs_byte(((char *) &tmp)[i],i + (char *) statbuf);
34 }
35
//// �ļ�״̬ϵͳ���á�
// ���ݸ������ļ�����ȡ����ļ�״̬��Ϣ��
// ����filename��ָ�����ļ�����statbuf�Ǵ��״̬��Ϣ�Ļ�����ָ�롣
// ���أ��ɹ�����0���������س����롣
36 int sys_stat(char * filename, struct stat * statbuf)
37 {
38 struct m_inode * inode;
39
// ���ȸ����ļ����ҳ���Ӧ��i�ڵ㡣Ȼ��i�ڵ��ϵ��ļ�״̬��Ϣ���Ƶ��û��������У�
// ���Żظ�i�ڵ㡣
40 if (!(inode=namei(filename)))
41 return -ENOENT;
42 cp_stat(inode,statbuf);
43 iput(inode);
44 return 0;
45 }
46
//// �ļ�״̬ϵͳ���á�
// ���ݸ������ļ�����ȡ����ļ�״̬��Ϣ���ļ�·�������з��������ļ�������ȡ�����ļ�
// ��״̬��
// ����filename��ָ�����ļ�����statbuf�Ǵ��״̬��Ϣ�Ļ�����ָ�롣
// ���أ��ɹ�����0���������س����롣
47 int sys_lstat(char * filename, struct stat * statbuf)
48 {
49 struct m_inode * inode;
50
// ���ȸ����ļ����ҳ���Ӧ��i�ڵ㡣Ȼ��i�ڵ��ϵ��ļ�״̬��Ϣ���Ƶ��û��������У�
// ���Żظ�i�ڵ㡣
51 if (!(inode = lnamei(filename))) // ȡָ��·����i�ڵ㣬������������ӡ�
52 return -ENOENT;
53 cp_stat(inode,statbuf);
54 iput(inode);
55 return 0;
56 }
57
//// �ļ�״̬ϵͳ���á�
// ���ݸ������ļ������ȡ����ļ�״̬��Ϣ��
// ����fd��ָ���ļ��ľ��(������)��statbuf�Ǵ��״̬��Ϣ�Ļ�����ָ�롣
// ���أ��ɹ�����0���������س����롣
58 int sys_fstat(unsigned int fd, struct stat * statbuf)
59 {
60 struct file * f;
61 struct m_inode * inode;
62
// ����ȡ�ļ������Ӧ���ļ��ṹ��Ȼ����еõ��ļ���i�ڵ㡣Ȼ��i�ڵ��ϵ��ļ�״
// ̬��Ϣ���Ƶ��û��������С�����ļ����ֵ����һ�����������ļ���NR_OPEN����
// �߸þ�����ļ��ṹָ��Ϊ�գ����߶�Ӧ�ļ��ṹ��i�ڵ��ֶ�Ϊ�գ�����������س���
// �벢�˳���
63 if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))
64 return -EBADF;
65 cp_stat(inode,statbuf);
66 return 0;
67 }
68
//// �����������ļ�ϵͳ���á�
// �õ��ö�ȡ���������ļ������ݣ����÷���������ָ���ļ���·�����ַ����������ŵ�ָ��
// ���ȵ��û��������С���������̫С���ͻ�ضϷ������ӵ����ݡ�
// ������path -- ���������ļ�·������buf -- �û���������bufsiz -- ���������ȡ�
// ���أ��ɹ��ط��뻺�����е��ַ�������ʧ���س����롣
69 int sys_readlink(const char * path, char * buf, int bufsiz)
70 {
71 struct m_inode * inode;
72 struct buffer_head * bh;
73 int i;
74 char c;
75
// ���ȼ�����֤������������Ч�ԣ���������е������û��������ֽڳ���bufsi������
// 1--1023֮�䡣Ȼ��ȡ�÷��������ļ�����i�ڵ㣬����ȡ���ļ��ĵ�1���������ݡ�֮
// ��Ż�i�ڵ㡣
76 if (bufsiz <= 0)
77 return -EBADF;
78 if (bufsiz > 1023)
79 bufsiz = 1023;
80 verify_area(buf,bufsiz);
81 if (!(inode = lnamei(path)))
82 return -ENOENT;
83 if (inode->i_zone[0])
84 bh = bread(inode->i_dev, inode->i_zone[0]);
85 else
86 bh = NULL;
87 iput(inode);
// �����ȡ�ļ��������ݳɹ�����������и������bufsiz���ַ����û��������С�������
// NULL�ַ�������ͷŻ���飬�����ظ��Ƶ��ֽ�����
88 if (!bh)
89 return 0;
90 i = 0;
91 while (i<bufsiz && (c = bh->b_data[i])) {
92 i++;
93 put_fs_byte(c,buf++);
94 }
95 brelse(bh);
96 return i;
97 }
98
1 /*
2 * linux/fs/fcntl.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
10 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
11 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
12
13 #include <fcntl.h> // �ļ�����ͷ�ļ��������ļ������������IJ������Ƴ������š�
14 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͳ�����
15
16 extern int sys_close(int fd); // �ر��ļ�ϵͳ���á�(fs/open.c, 192)
17
//// ���������������������
// ����fd�������Ƶ��ļ������argָ�����ļ��������С��ֵ��
// �������ļ����������롣
18 static int dupfd(unsigned int fd, unsigned int arg)
19 {
// ���ȼ�麯����������Ч�ԡ�����ļ����ֵ����һ�����������ļ���NR_OPEN������
// �þ�����ļ��ṹ�����ڣ��س����벢�˳������ָ�����¾��ֵarg����������
// ������Ҳ���س����벢�˳���ע�⣬ʵ�����ļ�������ǽ����ļ��ṹָ�������������š�
20 if (fd >= NR_OPEN || !current->filp[fd])
21 return -EBADF;
22 if (arg >= NR_OPEN)
23 return -EINVAL;
// Ȼ���ڵ�ǰ���̵��ļ��ṹָ��������Ѱ�������ŵ��ڻ����arg������û��ʹ�õ����
// �ҵ����¾��ֵarg���������ļ�������û�п�������س����벢�˳���
24 while (arg < NR_OPEN)
25 if (current->filp[arg])
26 arg++;
27 else
28 break;
29 if (arg >= NR_OPEN)
30 return -EMFILE;
// ��������ҵ��Ŀ�������������ִ��ʱ�رձ�־λͼclose_on_exec�и�λ�þ��λ��
// ��������exec()�ຯ��ʱ������ر���dup()�����ľ����������ļ��ṹָ�����ԭ��
// ��fd��ָ�룬���ҽ��ļ����ü�����1������µ��ļ����arg��
31 current->close_on_exec &= ~(1<<arg);
32 (current->filp[arg] = current->filp[fd])->f_count++;
33 return arg;
34 }
35
//// �����ļ����ϵͳ���á�
// ����ָ���ļ����oldfd�����ļ����ֵ����newfd�����newfd�Ѵ������ȹر�֮��
// ������oldfd -- ԭ�ļ������newfd - ���ļ������
// �������ļ����ֵ��
36 int sys_dup2(unsigned int oldfd, unsigned int newfd)
37 {
38 sys_close(newfd); // �����newfd�Ѿ��������ȹر�֮��
39 return dupfd(oldfd,newfd); // ���Ʋ������¾����
40 }
41
//// �����ļ����ϵͳ���á�
// ����ָ���ļ����oldfd���¾����ֵ�ǵ�ǰ��С��δ�þ��ֵ��
// ������fildes -- �����Ƶ��ļ������
// �������ļ����ֵ��
42 int sys_dup(unsigned int fildes)
43 {
44 return dupfd(fildes,0);
45 }
46
//// �ļ�����ϵͳ���ú�����
// ����fd���ļ������cmd�ǿ�������μ�include/fcntl.h��23-30�У���arg����Բ�
// ͬ�������в�ͬ�ĺ��塣���ڸ��ƾ������F_DUPFD��arg�����ļ������ȡ����Сֵ����
// �������ļ������ͷ��ʱ�־����F_SETFL��arg���µ��ļ������ͷ���ģʽ�������ļ�����
// ����F_GETLK��F_SETLK��F_SETLKW��arg��ָ��flock�ṹ��ָ�롣�����ں���û��ʵ��
// �ļ��������ܡ�
// ���أ��������������в���������-1�����ɹ�����ôF_DUPFD �������ļ������ F_GETFD
// �����ļ�����ĵ�ǰִ��ʱ�رձ�־close_on_exec��F_GETFL�����ļ������ͷ��ʱ�־��
47 int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
48 {
49 struct file * filp;
50
// ���ȼ��������ļ��������Ч�ԡ�Ȼ����ݲ�ͬ����cmd ���зֱ����� ����ļ����
// ֵ����һ�����������ļ���NR_OPEN�����߸þ�����ļ��ṹָ��Ϊ�գ��س�����
// ���˳���
51 if (fd >= NR_OPEN || !(filp = current->filp[fd]))
52 return -EBADF;
53 switch (cmd) {
54 case F_DUPFD: // ����������
55 return dupfd(fd,arg);
56 case F_GETFD: // ȡ�ļ������ִ��ʱ�رձ�־��
57 return (current->close_on_exec>>fd)&1;
58 case F_SETFD: // ����ִ��ʱ�رձ�־��argλ0��λ�����ã�����رա�
59 if (arg&1)
60 current->close_on_exec |= (1<<fd);
61 else
62 current->close_on_exec &= ~(1<<fd);
63 return 0;
64 case F_GETFL: // ȡ�ļ�״̬��־�ͷ���ģʽ��
65 return filp->f_flags;
66 case F_SETFL: // �����ļ�״̬�ͷ���ģʽ������arg�������ӡ���������־����
67 filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
68 filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
69 return 0;
70 case F_GETLK: case F_SETLK: case F_SETLKW: // δʵ�֡�
71 return -1;
72 default:
73 return -1;
74 }
75 }
76
1 /*
2 * linux/fs/ioctl.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͳ�����
10
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0���ݵȡ�
12
13 extern int tty_ioctl(int dev, int cmd, int arg); // chr_drv/tty_ioctl.c����133��
14 extern int pipe_ioctl(struct m_inode *pino, int cmd, int arg); // fs/pipe.c����118��
15
// ���������������(ioctl)����ָ�����͡�
16 typedef int (*ioctl_ptr)(int dev,int cmd,int arg);
17
// ȡϵͳ���豸�����ĺꡣ
18 #define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))
19
// ioctl��������ָ�����
20 static ioctl_ptr ioctl_table[]={
21 NULL, /* nodev */
22 NULL, /* /dev/mem */
23 NULL, /* /dev/fd */
24 NULL, /* /dev/hd */
25 tty_ioctl, /* /dev/ttyx */
26 tty_ioctl, /* /dev/tty */
27 NULL, /* /dev/lp */
28 NULL}; /* named pipes */
29
30
//// ϵͳ���ú��� - ����������ƺ�����
// �ú��������жϲ����������ļ��������Ƿ���Ч��Ȼ����ݶ�Ӧi�ڵ����ļ������ж��ļ�
// ���ͣ������ݾ����ļ����͵�����صĴ���������
// ������fd - �ļ���������cmd - �����룻arg - ������
// ���أ��ɹ���0�����س����롣
31 int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
32 {
33 struct file * filp;
34 int dev,mode;
35
// �����жϸ������ļ�����������Ч�ԡ�����ļ������������ɴ��ļ��������߶�Ӧ����
// �����ļ��ṹָ��Ϊ�գ��س������˳���
36 if (fd >= NR_OPEN || !(filp = current->filp[fd]))
37 return -EBADF;
// ����ļ��ṹ��Ӧ���ǹܵ�i�ڵ㣬����ݽ����Ƿ���Ȩ�����ùܵ�ȷ���Ƿ�ִ�йܵ�IO
// ���Ʋ���������Ȩִ�������pipe_ioctl()��������Ч�ļ������롣
38 if (filp->f_inode->i_pipe)
39 return (filp->f_mode&1)?pipe_ioctl(filp->f_inode,cmd,arg):-EBADF;
// �������������ļ���ȡ��Ӧ�ļ������ԣ����ݴ��ж��ļ������͡�������ļ��Ȳ����ַ���
// ���ļ���Ҳ���ǿ��豸�ļ����س������˳��������ַ�����豸�ļ�������ļ���i��
// ����ȡ�豸�š�����豸�Ŵ���ϵͳ���е��豸�����س����š�
40 mode=filp->f_inode->i_mode;
41 if (!S_ISCHR(mode) && !S_ISBLK(mode))
42 return -EINVAL;
43 dev = filp->f_inode->i_zone[0];
44 if (MAJOR(dev) >= NRDEVS)
45 return -ENODEV;
// Ȼ�����IO���Ʊ�ioctl_table��ö�Ӧ�豸��ioctl����ָ�룬�����øú������������
// ����ioctl����ָ�����û�ж�Ӧ�������س����롣
46 if (!ioctl_table[MAJOR(dev)])
47 return -ENOTTY;
48 return ioctl_table[MAJOR(dev)](dev,cmd,arg);
49 }
50
1 /*
2 * This file contains the procedures for the handling of select
3 *
4 * Created for Linux based loosely upon Mathius Lattner's minix
5 * patches by Peter MacDonald. Heavily edited by Linus.
6 */
/*
* ���ļ����д���select()ϵͳ���õĹ��̡�
*
* ����Peter MacDonald����Mathius Lattner�ṩ��MINIXϵͳ�IJ���
* �����Ķ��ɡ�
*/
7
8 #include <linux/fs.h>
9 #include <linux/kernel.h>
10 #include <linux/tty.h>
11 #include <linux/sched.h>
12
13 #include <asm/segment.h>
14 #include <asm/system.h>
15
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <string.h>
19 #include <const.h>
20 #include <errno.h>
21 #include <sys/time.h>
22 #include <signal.h>
23
24 /*
25 * Ok, Peter made a complicated, but straightforward multiple_wait() function.
26 * I have rewritten this, taking some shortcuts: This code may not be easy to
27 * follow, but it should be free of race-conditions, and it's practical. If you
28 * understand what I'm doing here, then you understand how the linux sleep/wakeup
29 * mechanism works.
30 *
31 * Two very simple procedures, add_wait() and free_wait() make all the work. We
32 * have to have interrupts disabled throughout the select, but that's not really
33 * such a loss: sleeping automatically frees interrupts when we aren't in this
34 * task.
35 */
/*
* OK��Peter�����˸��ӵ���ֱ�۵Ķ��_wait()�������Ҷ���Щ���������˸�д����ʹ֮
* ����ࣺ��Щ������ܲ�����������������Ӧ�ò�����ھ����������⣬���Һ�ʵ�ʡ�
* �����������������ƵĴ��룬��ô��˵�����Ѿ�����Linux��˯��/���ѵĹ������ơ�
*
* �����ܼĹ��̣�add_wait()��free_wait()ִ������Ҫ������������select����
* ���������Dz��ò���ֹ�жϡ��������������������̫�����ʧ����Ϊ�����Dz���ִ��
* ������ʱ˯��״̬���Զ����ͷ��жϣ������������ʹ���Լ�EFLAGS�е��жϱ�־����
*/
36
37 typedef struct {
38 struct task_struct * old_task;
39 struct task_struct ** wait_address;
40 } wait_entry;
41
42 typedef struct {
43 int nr;
44 wait_entry entry[NR_OPEN*3];
45 } select_table;
46
// ��δ�����������ĵȴ�����ָ�����ȴ���wait_table�С�����*wait_address��������
// ����صĵȴ�����ͷָ�롣����tty���������secondary�ĵȴ�����ͷָ����proc_list��
// ���� p��do_select()�ж���ĵȴ����ṹָ�롣
47 static void add_wait(struct task_struct ** wait_address, select_table * p)
48 {
49 int i;
50
// �����ж��������Ƿ��ж�Ӧ�ĵȴ����У������ء�Ȼ���ڵȴ�������������ָ���ĵȴ�
// ����ָ���Ƿ��Ѿ��ڵȴ��������ù��������ù�Ҳ���̷��ء�����ж���Ҫ����Թܵ��ļ�
// ��������������һ���ܵ��ڵȴ����Խ��ж���������ô��ض��������̽���д������
51 if (!wait_address)
52 return;
53 for (i = 0 ; i < p->nr ; i++)
54 if (p->entry[i].wait_address == wait_address)
55 return;
// Ȼ�����ǰ���������Ӧ�ȴ����е�ͷָ�뱣���ڵȴ���wait_table�У�ͬʱ�õȴ������
// old_task�ֶ�ָ��ȴ�����ͷָ��ָ�������������ΪNULL�������õȴ�����ͷָ��ָ
// ��ǰ�������ѵȴ�����Ч�����ֵnr��1�����ڵ�179�б���ʼ��Ϊ0����
56 p->entry[p->nr].wait_address = wait_address;
57 p->entry[p->nr].old_task = * wait_address;
58 *wait_address = current;
59 p->nr++;
60 }
61
// ��յȴ����������ǵȴ����ṹָ�롣��������do_select()������˯�ߺ��ѷ���ʱ������
// ����204��207�У������ڻ��ѵȴ����д��ڸ����ȴ������ϵ�������������kernel/sched.c
// ��sleep_on()�����ĺ�벿�ִ��뼸����ȫ��ͬ����ο���sleep_on()������˵����
62 static void free_wait(select_table * p)
63 {
64 int i;
65 struct task_struct ** tpp;
66
// ����ȴ����и����nr ����Ч���¼�ĵȴ�����ͷָ��������������������ӽ��ĵȴ�
// ���������������̵��� sleep_on() ������˯���ڸõȴ������ϣ������ʱ�ȴ�����ͷָ��
// ָ��IJ��ǵ�ǰ���̣���ô���Ǿ���Ҫ�Ȼ�����Щ�����������ǽ��ȴ�����ͷ��ָ������
// ��Ϊ����״̬��state = 0���������Լ�����Ϊ�����жϵȴ�״̬�����Լ�Ҫ�ȴ���Щ��������
// �е������Ѷ�ִ��ʱ�����ѱ�����Ȼ������ִ�е��ȳ���
67 for (i = 0; i < p->nr ; i++) {
68 tpp = p->entry[i].wait_address;
69 while (*tpp && *tpp != current) {
70 (*tpp)->state = 0;
71 current->state = TASK_UNINTERRUPTIBLE;
72 schedule();
73 }
// ִ�е����˵���ȴ�����ǰ�������еĵȴ�����ͷָ���ֶ�wait_addressָ��ǰ����
// ����Ϊ�գ���������������⣬������ʾ������Ϣ��Ȼ�������õȴ�����ͷָ��ָ��������
// ǰ�������е�����76�У�������ʱ��ͷָ��ȷʵָ��һ�����������NULL����˵��
// �����л�������*tpp��Ϊ�գ������ǽ����������óɾ���״̬������֮�����ѵȴ�����
// ��Ч��������ֶ�nr���㡣
74 if (!*tpp)
75 printk("free_wait: NULL");
76 if (*tpp = p->entry[i].old_task)
77 (**tpp).state = 0;
78 }
79 p->nr = 0;
80 }
81
// �����ļ�i�ڵ��ж��ļ��Ƿ����ַ��ն��豸�ļ�����������tty�ṹָ�룬����NULL��
82 static struct tty_struct * get_tty(struct m_inode * inode)
83 {
84 int major, minor;
85
// ��������ַ��豸�ļ���NULL��������豸�Ų���5�������նˣ���4����NULL��
86 if (!S_ISCHR(inode->i_mode))
87 return NULL;
88 if ((major = MAJOR(inode->i_zone[0])) != 5 && major != 4)
89 return NULL;
// ������豸����5����ô���ն��豸�ŵ��ڽ��̵�tty�ֶ�ֵ������͵����ַ��豸�ļ����豸�š�
// ����ն��豸��С��0����ʾ����û�п����ն˻�û��ʹ���նˣ����Ƿ���NULL�����ض�Ӧ��
// tty�ṹָ�롣
90 if (major == 5)
91 minor = current->tty;
92 else
93 minor = MINOR(inode->i_zone[0]);
94 if (minor < 0)
95 return NULL;
96 return TTY_TABLE(minor);
97 }
98
99 /*
100 * The check_XX functions check out a file. We know it's either
101 * a pipe, a character device or a fifo (fifo's not implemented)
102 */
/*
* check_XX�������ڼ��һ���ļ�������֪�����ļ�Ҫô�ǹܵ��ļ���
* Ҫô���ַ��豸�ļ�������Ҫô��һ��FIFO��FIFO��δʵ�֣���
*/
// �����ļ������Ƿ����ã����ն˶��������secondary�Ƿ����ַ��ɶ������߹ܵ��ļ��Ƿ�
// ���ա�����wait�ǵȴ���ָ�룻inode���ļ�i�ڵ�ָ�롣���������ɽ��ж�������1����
// ��0��
103 static int check_in(select_table * wait, struct m_inode * inode)
104 {
105 struct tty_struct * tty;
106
// ���ȸ����ļ�i�ڵ����get_tty()����ļ��Ƿ���һ��tty�նˣ��ַ����豸�ļ����������
// �����ն˶��������secondary���Ƿ����ַ��ɹ���ȡ��������1������ʱsecondaryΪ
// ����ѵ�ǰ�������ӵ�secondary�ĵȴ�����proc_list�ϲ�����0������ǹܵ��ļ������ж�
// Ŀǰ�ܵ����Ƿ����ַ��ɶ���������1����û�У��ܵ��գ���ѵ�ǰ�������ӵ��ܵ�i�ڵ�
// �ĵȴ������ϲ�����0��ע�⣬PIPE_EMPTY()��ʹ�ùܵ���ǰͷβָ��λ�����жϹܵ��Ƿ�ա�
// �ܵ�i�ڵ��i_zone[0]��i_zone[1]�ֶηֱ����Źܵ���ǰ��ͷβָ�롣
107 if (tty = get_tty(inode))
108 if (!EMPTY(tty->secondary))
109 return 1;
110 else
111 add_wait(&tty->secondary->proc_list, wait);
112 else if (inode->i_pipe)
113 if (!PIPE_EMPTY(*inode))
114 return 1;
115 else
116 add_wait(&inode->i_wait, wait);
117 return 0;
118 }
119
// ����ļ�д�����Ƿ����ã����ն�д�������write_q���Ƿ��п���λ�ÿ�д�����ߴ�ʱ��
// ���ļ��Ƿ���������wait�ǵȴ���ָ�룻inode���ļ�i�ڵ�ָ�롣���������ɽ���д������
// ����1������0��
120 static int check_out(select_table * wait, struct m_inode * inode)
121 {
122 struct tty_struct * tty;
123
// ���ȸ����ļ�i�ڵ����get_tty()����ļ��Ƿ���һ��tty�նˣ��ַ����豸�ļ����������
// �����ն�д�������write_q���Ƿ��пռ��д�룬������1����û�пտռ���ѵ�ǰ��
// �����ӵ�write_q�ĵȴ�����proc_list�ϲ�����0������ǹܵ��ļ����ж�Ŀǰ�ܵ����Ƿ���
// ���пռ��д���ַ���������1����û�У��ܵ�������ѵ�ǰ�������ӵ��ܵ�i�ڵ�ĵȴ�
// �����ϲ�����0��
124 if (tty = get_tty(inode))
125 if (!FULL(tty->write_q))
126 return 1;
127 else
128 add_wait(&tty->write_q->proc_list, wait);
129 else if (inode->i_pipe)
130 if (!PIPE_FULL(*inode))
131 return 1;
132 else
133 add_wait(&inode->i_wait, wait);
134 return 0;
135 }
136
// ����ļ��Ƿ����쳣״̬�������ն��豸�ļ���Ŀǰ�ں����Ƿ���0�����ڹܵ��ļ������
// ��ʱ�����ܵ�����������һ�����ѱ��رգ���1������Ͱѵ�ǰ�������ӵ��ܵ�i�ڵ�
// �ĵȴ������ϲ�����0������0������wait�ǵȴ���ָ�룻inode���ļ�i�ڵ�ָ�롣������
// �쳣������1������0��
137 static int check_ex(select_table * wait, struct m_inode * inode)
138 {
139 struct tty_struct * tty;
140
141 if (tty = get_tty(inode))
142 if (!FULL(tty->write_q))
143 return 0;
144 else
145 return 0;
146 else if (inode->i_pipe)
147 if (inode->i_count < 2)
148 return 1;
149 else
150 add_wait(&inode->i_wait,wait);
151 return 0;
152 }
153
// do_select() ���ں�ִ��select()ϵͳ���õ�ʵ�ʴ����������ú������ȼ�����������и���
// ����������Ч�ԣ�Ȼ��ֱ�����������������������麯��check_XX()��ÿ�����������м�
// �飬ͬʱͳ�����������е�ǰ�Ѿ����õ������������������κ�һ���������Ѿ����ã���
// �����ͻ����̷��أ�������̾ͻ��ڱ������н���˯��״̬�����ڹ��˳�ʱʱ���������ij��
// ���������ڵȴ������ϵĽ��̱����Ѷ�ʹ�����̼������С�
154 int do_select(fd_set in, fd_set out, fd_set ex,
155 fd_set *inp, fd_set *outp, fd_set *exp)
156 {
157 int count; // �����õ���������������ֵ��
158 select_table wait_table; // �ȴ����ṹ��
159 int i;
160 fd_set mask;
161
// ���Ȱ�3�������������л��������mask�еõ�������������Ч����������λ�����롣 Ȼ��
// ѭ���жϵ�ǰ���̸����������Ƿ���Ч���Ұ��������������ڡ���ѭ���У�ÿ�ж���һ������
// ���ͻ��mask����1λ����˸���mask�������Ч����λ���ǾͿ����ж���Ӧ�������Ƿ���
// �û����������������С���Ч��������Ӧ����һ���ܵ��ļ���������������һ���ַ��豸�ļ�
// ��������������һ��FIFO���������������͵Ķ���Ϊ��Ч������������EBADF����
162 mask = in | out | ex;
163 for (i = 0 ; i < NR_OPEN ; i++,mask >>= 1) {
164 if (!(mask & 1)) // ����������������������ж���һ����
165 continue;
166 if (!current->filp[i]) // �����ļ�δ��������������
167 return -EBADF;
168 if (!current->filp[i]->f_inode) // ���ļ�i�ڵ�ָ��գ��ش���š�
169 return -EBADF;
170 if (current->filp[i]->f_inode->i_pipe) // ���ǹܵ��ļ�������������Ч��
171 continue;
172 if (S_ISCHR(current->filp[i]->f_inode->i_mode)) // �ַ��豸�ļ���Ч��
173 continue;
174 if (S_ISFIFO(current->filp[i]->f_inode->i_mode)) // FIFOҲ��Ч��
175 continue;
176 return -EBADF; // �����Ϊ��Ч�����������ء�
177 }
// ���濪ʼѭ�����3�����������еĸ����������Ƿ����ã����Բ���������ʱmask������ǰ
// ���ڴ����������������롣ѭ���е�3������check_in()��check_out()��check_ex()�ֱ���
// ���ж��������Ƿ��Ѿ����á���һ���������Ѿ����ã���������������������ö�Ӧ����
// λ�����Ұ���������������������ֵcount��1����183��forѭ������е� mask += mask
// ���� mask<< 1��
178 repeat:
179 wait_table.nr = 0;
180 *inp = *outp = *exp = 0;
181 count = 0;
182 mask = 1;
183 for (i = 0 ; i < NR_OPEN ; i++, mask += mask) {
// �����ʱ�жϵ��������ڶ��������������У����Ҹ��������Ѿ����ÿ��Խ��ж����������
// ������������������in�ж�Ӧ����λ��Ϊ1��ͬʱ����������������������ֵcount��1��
184 if (mask & in)
185 if (check_in(&wait_table,current->filp[i]->f_inode)) {
186 *inp |= mask; // �������������ö�Ӧ����λ��
187 count++; // ����������������������
188 }
// �����ʱ�жϵ���������д�������������У����Ҹ��������Ѿ����ÿ��Խ���д���������
// ������������������out�ж�Ӧ����λ��Ϊ1��ͬʱ����������������������ֵcount��1��
189 if (mask & out)
190 if (check_out(&wait_table,current->filp[i]->f_inode)) {
191 *outp |= mask;
192 count++;
193 }
// �����ʱ�жϵ����������쳣���������У����Ҹ��������Ѿ����쳣���֣���Ѹ�����������
// ������ex�ж�Ӧ����λ��Ϊ1��ͬʱ����������������������ֵcount��1��
194 if (mask & ex)
195 if (check_ex(&wait_table,current->filp[i]->f_inode)) {
196 *exp |= mask;
197 count++;
198 }
199 }
// �ڶԽ��������������жϴ���������û�з����������õ���������count==0�������Ҵ�ʱ
// ����û���յ��κη������źţ����Ҵ�ʱ�еȴ��ŵ����������ߵȴ�ʱ�仹û�г�ʱ����ô��
// �ǾͰѵ�ǰ����״̬���óɿ��ж�˯��״̬��Ȼ��ִ�е��Ⱥ���ȥִ�����������ں���һ
// �ε���ִ�б�����ʱ�͵���free_wait()������صȴ������ϱ�����ǰ�������Ȼ����ת��
// repeat��Ŵ���178�У��ٴ����¼���Ƿ������ǹ��ĵģ����������еģ������������á�
200 if (!(current->signal & ~current->blocked) &&
201 (wait_table.nr || current->timeout) && !count) {
202 current->state = TASK_INTERRUPTIBLE;
203 schedule();
204 free_wait(&wait_table); // �������ѷ��غ�����↑ʼִ�С�
205 goto repeat;
206 }
// �����ʱcount������0�����߽��յ����źţ����ߵȴ�ʱ�䵽����û����Ҫ�ȴ�����������
// ��ô���Ǿ͵���free_wait()���ѵȴ������ϵ�����Ȼ�������õ�����������ֵ��
207 free_wait(&wait_table);
208 return count;
209 }
210
211 /*
212 * Note that we cannot return -ERESTARTSYS, as we change our input
213 * parameters. Sad, but there you are. We could do some tweaking in
214 * the library function ...
215 */
/*
* ע�����Dz��ܷ���-ERESTARTSYS����Ϊ���ǻ���select���й����иı�
* �������ֵ��*timeout�����ܲ��ң�����Ҳֻ�ܽ��������ʵ����������
* �����ڿ⺯������Щ����...
*/
// selectϵͳ���ú������ú����еĴ�����Ҫ�������select���ܲ���ǰ��IJ������ƺ�ת��
// ������select��Ҫ�Ĺ�����do_select()��������ɡ�sys_select()�����ȸ��ݲ�����������
// ������ָ����û����ݿռ�� select() �������õIJ����ֽ⸴�Ƶ��ں˿ռ䣬Ȼ��������Ҫ
// �ȴ��ij�ʱʱ��ֵtimeout�����ŵ���do_select() ִ�� select���ܣ����غ�ͰѴ������
// �ٸ��ƻ��û��ռ��С�
// ����bufferָ���û���������select()�����ĵ�1�����������������ֵС��0��ʾִ��ʱ
// ���ִ����������ֵ����0�����ʾ�ڹ涨�ȴ�ʱ����û�����������ò������������ֵ
// ����0�����ʾ�����õ�������������
216 int sys_select( unsigned long *buffer )
217 {
218 /* Perform the select(nd, in, out, ex, tv) system call. */
/* ִ��select(nd, in, out, ex, tv)ϵͳ���� */
// ���ȶ��弸���ֲ����������ڰ�ָ�������������select()���������ֽ����
219 int i;
220 fd_set res_in, in = 0, *inp; // ����������������
221 fd_set res_out, out = 0, *outp; // �������������
222 fd_set res_ex, ex = 0, *exp; // �쳣��������������
223 fd_set mask; // ��������������ֵ��Χ��nd�������롣
224 struct timeval *tvp; // �ȴ�ʱ��ṹָ�롣
225 unsigned long timeout;
226
// Ȼ����û��������Ѳ����ֱ���븴�Ƶ��ֲ�ָ������У���������������ָ���Ƿ���Ч�ֱ�
// ȡ��3����������in��������out��д����ex���쳣�������� mask Ҳ��һ����������������
// ����3�����������������������ֵ+1������1������nd��ֵ�����������ó��û�������ĵ�
// �����������������롣���磬��nd = 4����mask = 0b00001111����32���أ���
227 mask = ~((~0) << get_fs_long(buffer++));
228 inp = (fd_set *) get_fs_long(buffer++);
229 outp = (fd_set *) get_fs_long(buffer++);
230 exp = (fd_set *) get_fs_long(buffer++);
231 tvp = (struct timeval *) get_fs_long(buffer);
232
233 if (inp) // ��ָ����Ч����ȡ����������������
234 in = mask & get_fs_long(inp);
235 if (outp) // ��ָ����Ч����ȡд��������������
236 out = mask & get_fs_long(outp);
237 if (exp) // ��ָ����Ч����ȡ�쳣����������
238 ex = mask & get_fs_long(exp);
// ���������dz��Դ�ʱ��ṹ��ȡ���ȴ���˯�ߣ�ʱ��ֵtimeout�����Ȱ�timeout��ʼ�������
// �����ޣ�ֵ��Ȼ����û����ݿռ�ȡ�ø�ʱ��ṹ�����õ�ʱ��ֵ����ת���ͼ���ϵͳ��ǰ�δ�
// ֵjiffies�����õ���Ҫ�ȴ���ʱ��δ���ֵ timeout�������ô�ֵ�����õ�ǰ����Ӧ�õȴ�
// ����ʱ�����⣬��241����tv_usec�ֶ�����ֵ����������1000000��ɵõ���Ӧ�������ٳ�
// ��ϵͳÿ��δ���HZ������tv_usecת���ɵδ�ֵ��
239 timeout = 0xffffffff;
240 if (tvp) {
241 timeout = get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
242 timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
243 timeout += jiffies;
244 }
245 current->timeout = timeout; // ���õ�ǰ����Ӧ����ʱ�ĵδ�ֵ��
// select()��������Ҫ������do_select()����ɡ��ڵ��øú���֮��Ĵ������ڰѴ����������
// ���û��������У����ظ��û���Ϊ�˱�����־����������ڵ���do_select()ǰ��Ҫ��ֹ�жϣ�
// ���ڸú������غ��ٿ����жϡ�
// �����do_select()����֮����̵ĵȴ���ʱ�ֶ�timeout�����ڵ�ǰϵͳ��ʱ�δ�ֵjiffies��
// ˵���ڳ�ʱ֮ǰ�Ѿ������������ã��������������ȼ��µ���ʱ��ʣ���ʱ��ֵ��������ǻ�
// �����ֵ���ظ��û���������̵ĵȴ���ʱ�ֶ�timeout�Ѿ�С�ڻ���ڵ�ǰϵͳjiffies����
// ʾdo_select()���������ڳ�ʱ�����أ���˰�ʣ��ʱ��ֵ����Ϊ0��
246 cli(); // ��ֹ��Ӧ�жϡ�
247 i = do_select(in, out, ex, &res_in, &res_out, &res_ex);
248 if (current->timeout > jiffies)
249 timeout = current->timeout - jiffies;
250 else
251 timeout = 0;
252 sti(); // �����ж���Ӧ��
// ���������ǰѽ��̵ij�ʱ�ֶ����㡣���do_select()���ص�����������������С��0����ʾ
// ִ�г��������Ƿ����������š�Ȼ�����ǰѴ������������������ݺ��ӳ�ʱ��ṹ����д�ص�
// �û����ݻ���ռ䡣��дʱ��ṹ����ʱ����Ҫ�Ƚ��δ�ʱ�䵥λ��ʾ��ʣ���ӳ�ʱ��ת������
// ����ֵ��
253 current->timeout = 0;
254 if (i < 0)
255 return i;
256 if (inp) {
257 verify_area(inp, 4);
258 put_fs_long(res_in,inp); // �ɶ�����������
259 }
260 if (outp) {
261 verify_area(outp,4);
262 put_fs_long(res_out,outp); // �����������
263 }
264 if (exp) {
265 verify_area(exp,4);
266 put_fs_long(res_ex,exp); // �����쳣��������������
267 }
268 if (tvp) {
269 verify_area(tvp, sizeof(*tvp));
270 put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec); // �롣
271 timeout %= HZ;
272 timeout *= (1000000/HZ);
273 put_fs_long(timeout, (unsigned long *) &tvp->tv_usec); // �롣
274 }
// �����ʱ��û�������õ��������������յ���ij���������źţ��ر��жϴ���š�
// ���������õ�����������ֵ��
275 if (!i && (current->signal & ~current->blocked))
276 return -EINTR;
277 return i;
278 }
279
1 /*
2 * linux/mm/memory.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * demand-loading started 01.12.91 - seems it is high on the list of
9 * things wanted, and it should be easy to implement. - Linus
10 */
/*
* ��������Ǵ�91.12.1��ʼ��д�� - �ڳ�����Ʊ����ƺ�������Ҫ�ij���
* ����Ӧ���Ǻ����ױ��Ƶ� - Linus
*/
11
12 /*
13 * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
14 * pages started 02.12.91, seems to work. - Linus.
15 *
16 * Tested sharing by executing about 30 /bin/sh: under the old kernel it
17 * would have taken more than the 6M I have free, but it worked well as
18 * far as I could see.
19 *
20 * Also corrected some "invalidate()"s - I wasn't doing enough of them.
21 */
/*
* OK����������DZȽ����ױ�д�ģ�������ҳ��ȴ��Ҫ�е㼼�ɡ�����ҳ�������
* 91.12.2��ʼ��д�ģ������ܹ����� - Linus��
*
* ͨ��ִ�д�Լ30��/bin/sh�Թ������������˲��ԣ������ں˵�����Ҫռ�ö���
* 6M���ڴ棬��Ŀǰȴ���á����ڿ��������úܺá�
*
* ��"invalidate()"����Ҳ���������� - ���ⷽ���һ����IJ�����
*/
22
23 /*
24 * Real VM (paging to/from disk) started 18.12.91. Much more work and
25 * thought has to go into this. Oh, well..
26 * 19.12.91 - works, somewhat. Sometimes I get faults, don't know why.
27 * Found it. Everything seems to work now.
28 * 20.12.91 - Ok, making the swap-device changeable like the root.
29 */
/*
* 91.12.18��ʼ��д�����������ڴ����VM������ҳ�浽/�Ӵ��̣�����Ҫ�Դ�
* ���Ǻܶಢ����Ҫ���ܶ�����Ǻǣ�Ҳֻ�������ˡ�
* 91.12.19 - ��ij�̶ֳ��Ͽ��Թ����ˣ�����ʱ���������֪����ô���¡�
* �ҵ������ˣ����ں���һ�ж��ܹ����ˡ�
* 91.12.20 - OK���ѽ����豸�ijɿɸ��ĵ��ˣ�������ļ��豸������
*/
30
31 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źź���ԭ�͡�
32
33 #include <asm/system.h> // ϵͳͷ�ļ����������û���������/�ж��ŵ�Ƕ����ꡣ
34
35 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0�����ݡ�
36 #include <linux/head.h> // headͷ�ļ���������������ļṹ���ͼ���ѡ���������
37 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
38
// CODE_SPACE(addr) ((((addr)+0xfff)&~0xfff)<current->start_code+current->end_code)��
// �ú������жϸ������Ե�ַ�Ƿ�λ�ڵ�ǰ���̵Ĵ�����У���(((addr)+4095)&~4095)������
// ȡ�����Ե�ַaddr�����ڴ�ҳ���ĩ�˵�ַ���μ�265�С�
39 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \
40 current->start_code + current->end_code)
41
42 unsigned long HIGH_MEMORY = 0; // ȫ�ֱ��������ʵ�������ڴ���߶˵�ַ��
43
// ��from������1ҳ�ڴ浽to����4K�ֽڣ���
44 #define copy_page(from,to) \
45 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")
46
// �����ڴ�ӳ���ֽ�ͼ��1�ֽڴ���1ҳ�ڴ棩��ÿ��ҳ���Ӧ���ֽ����ڱ�־ҳ�浱ǰ������
// ��ռ�ã���������������ӳ��15Mb���ڴ�ռ䡣�ڳ�ʼ������mem_init()�У����ڲ�����
// �����ڴ���ҳ���λ�þ���Ԥ�ȱ����ó�USED��100����
47 unsigned char mem_map [ PAGING_PAGES ] = {0,};
48
49 /*
50 * Free a page of memory at physical address 'addr'. Used by
51 * 'free_page_tables()'
52 */
/*
* �ͷ�������ַ'addr'����һҳ�ڴ档���ں���'free_page_tables()'��
*/
//// �ͷ�������ַaddr��ʼ��1ҳ���ڴ档
// ������ַ1MB���µ��ڴ�ռ������ں˳���ͻ��壬����Ϊ����ҳ����ڴ�ռ䡣���
// ����addr��Ҫ����1MB��
53 void free_page(unsigned long addr)
54 {
// �����жϲ���������������ַaddr�ĺ����ԡ����������ַaddrС���ڴ�Ͷˣ�1MB����
// ���ʾ���ں˳������ٻ����У��Դ˲��账�������������ַaddr >= ϵͳ��������
// �ڴ���߶ˣ�����ʾ������Ϣ�����ں�ֹͣ������
55 if (addr < LOW_MEM) return;
56 if (addr >= HIGH_MEMORY)
57 panic("trying to free nonexistent page");
// ����Բ���addr��֤ͨ������ô�������������ַ��������ڴ�Ͷ˿�ʼ������ڴ�
// ҳ��š�ҳ��� = (addr �C LOW_MEM)/4096���ɼ�ҳ��Ŵ�0�ſ�ʼ���𡣴�ʱaddr
// �д����ҳ��š������ҳ��Ŷ�Ӧ��ҳ��ӳ���ֽڲ�����0�����1���ء���ʱ��ӳ��
// �ֽ�ֵӦ��Ϊ0����ʾҳ�����ͷš������Ӧҳ���ֽ�ԭ������0����ʾ������ҳ�汾��
// ���ǿ��еģ�˵���ں˴�������⡣������ʾ������Ϣ��ͣ����
58 addr -= LOW_MEM;
59 addr >>= 12;
60 if (mem_map[addr]--) return;
61 mem_map[addr]=0;
62 panic("trying to free free page");
63 }
64
65 /*
66 * This function frees a continuos block of page tables, as needed
67 * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.
68 */
/*
* ���溯���ͷ�ҳ���������ڴ�飬'exit()'��Ҫ�ú�������copy_page_tables()
* ���ƣ��ú���������4Mb���ȵ��ڴ�顣
*/
//// ����ָ�������Ե�ַ������ҳ�����������ͷŶ�Ӧ�ڴ�ҳ��ָ�����ڴ�鲢�ñ�����С�
// ҳĿ¼λ��������ַ0��ʼ������1024�ÿ��4�ֽڣ���ռ4K�ֽڡ�ÿ��Ŀ¼��ָ��һ
// ��ҳ�����ں�ҳ����������ַ0x1000����ʼ��������Ŀ¼�ռ䣩����4��ҳ����ÿ��ҳ����
// 1024�ÿ��4�ֽڡ����Ҳռ4K��1ҳ���ڴ档�����̣��������ں˴����еĽ���0��1��
// ��ҳ����ռ�ݵ�ҳ���ڽ��̱�����ʱ���ں�Ϊ�������ڴ�������õ���ÿ��ҳ�����Ӧ1ҳ
// �����ڴ棬���һ��ҳ������ӳ��4MB�������ڴ档
// ������from - ��ʼ���Ի���ַ��size - �ͷŵ��ֽڳ��ȡ�
69 int free_page_tables(unsigned long from,unsigned long size)
70 {
71 unsigned long *pg_table;
72 unsigned long * dir, nr;
73
// ���ȼ�����from���������Ի���ַ�Ƿ���4MB�ı߽紦����Ϊ�ú���ֻ�ܴ������������
// ��from = 0���������˵����ͼ�ͷ��ں˺ͻ�����ռ�ռ䡣
74 if (from & 0x3fffff)
75 panic("free_page_tables called with wrong alignment");
76 if (!from)
77 panic("Trying to free up swapper memory space");
// Ȼ��������size�����ij�����ռ��ҳĿ¼������4MB�Ľ�λ����������Ҳ����ռҳ������
// ��Ϊ1��ҳ���ɹ���4MB�����ڴ棬��������������22λ�ķ�ʽ����Ҫ���Ƶ��ڴ泤��ֵ
// ����4MB�����м���0x3fffff����4Mb -1�����ڵõ���λ���������������������������
// ���1�����磬���ԭsize = 4.01Mb����ô�ɵõ����size = 2�� ���ż������������
// ����ַ��Ӧ����ʼĿ¼���Ӧ��Ŀ¼��� = from >> 22����Ϊÿ��ռ4�ֽڣ���������
// ҳĿ¼����������ַ0��ʼ��ţ����ʵ��Ŀ¼��ָ�� = Ŀ¼���<<2��Ҳ��(from>>20)��
// ��������0xffcȷ��Ŀ¼��ָ�뷶Χ��Ч��
78 size = (size + 0x3fffff) >> 22;
79 dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
// ��ʱ size ���ͷŵ�ҳ����������ҳĿ¼��������dir����ʼĿ¼��ָ�롣���ڿ�ʼѭ��
// ����ҳĿ¼������ͷ�ÿ��ҳ���е�ҳ��������ǰĿ¼����Ч��Pλ=0������ʾ��
// Ŀ¼��û��ʹ�ã���Ӧ��ҳ�������ڣ��������������һ��Ŀ¼������Ŀ¼����ȡ��
// ҳ����ַ pg_table�����Ը�ҳ���е� 1024 ��������д������ͷ���Чҳ���Pλ=1��
// ��Ӧ�������ڴ�ҳ�棬���ߴӽ����豸���ͷ���Чҳ���Pλ=0����Ӧ��ҳ�棬���ͷ�
// �����豸�ж�Ӧ���ڴ�ҳ�棨��Ϊҳ������Ѿ�������ȥ����Ȼ��Ѹ�ҳ�������㣬����
// ��������һҳ�����һ��ҳ�����б��������Ͼ��ͷŸ�ҳ������ռ�ݵ��ڴ�ҳ�棬
// ������������һҳĿ¼����ˢ��ҳ�任���ٻ��壬������0��
80 for ( ; size-->0 ; dir++) {
81 if (!(1 & *dir))
82 continue;
83 pg_table = (unsigned long *) (0xfffff000 & *dir); // ȡҳ����ַ��
84 for (nr=0 ; nr<1024 ; nr++) {
85 if (*pg_table) { // ����ָҳ�������ݲ�Ϊ0����
86 if (1 & *pg_table) // ��������Ч�����ͷŶ�Ӧҳ��
87 free_page(0xfffff000 & *pg_table);
88 else // �����ͷŽ����豸�ж�Ӧҳ��
89 swap_free(*pg_table >> 1);
90 *pg_table = 0; // ��ҳ�����������㡣
91 }
92 pg_table++; // ָ��ҳ������һ�
93 }
94 free_page(0xfffff000 & *dir); // �ͷŸ�ҳ����ռ�ڴ�ҳ�档
95 *dir = 0; // ��Ӧҳ����Ŀ¼�����㡣
96 }
97 invalidate(); // ˢ��CPUҳ�任���ٻ��塣
98 return 0;
99 }
100
101 /*
102 * Well, here is one of the most complicated functions in mm. It
103 * copies a range of linerar addresses by copying only the pages.
104 * Let's hope this is bug-free, 'cause this one I don't want to debug :-)
105 *
106 * Note! We don't copy just any chunks of memory - addresses have to
107 * be divisible by 4Mb (one page-directory entry), as this makes the
108 * function easier. It's used only by fork anyway.
109 *
110 * NOTE 2!! When from==0 we are copying kernel space for the first
111 * fork(). Then we DONT want to copy a full page-directory entry, as
112 * that would lead to some serious memory waste - we just copy the
113 * first 160 pages - 640kB. Even that is more than we need, but it
114 * doesn't take any more memory - we don't copy-on-write in the low
115 * 1 Mb-range, so the pages can be shared with the kernel. Thus the
116 * special case for nr=xxxx.
117 */
/*
* ���ˣ��������ڴ����mm����Ϊ���ӵij���֮һ����ͨ��ֻ�����ڴ�ҳ��
* ������һ����Χ�����Ե�ַ�е����ݡ� ϣ��������û�д�����Ϊ�Ҳ���
* �ٵ�����������:-)��
*
* ע�⣡���Dz��������κ��ڴ�� - �ڴ��ĵ�ַ��Ҫ��4Mb�ı���������
* һ��ҳĿ¼���Ӧ���ڴ泤�ȣ�����Ϊ����������ʹ�����ܼ� ������
* ����������fork()ʹ�á�
*
* ע��2���� ��from==0ʱ��˵������Ϊ��һ��fork()���ø����ں˿ռ䡣
* ��ʱ���ǾͲ��븴������ҳĿ¼���Ӧ���ڴ棬��Ϊ�������ᵼ���ڴ���
* ���˷� - ����ֻ�븴�ƿ�ͷ160��ҳ�� - ��Ӧ 640kB����ʹ�Ǹ�����Щ
* ҳ��Ҳ�Ѿ��������ǵ������ⲻ��ռ�ø�����ڴ� - �ڵ� 1Mb �ڴ�
* ��Χ�����Dz�ִ��дʱ���Ʋ�����������Щҳ��������ں˹����������
* ��nr=xxxx�����������nr�ڳ�����ָҳ��������
*/
//// ����ҳĿ¼�����ҳ���
// ����ָ�����Ե�ַ�ͳ����ڴ��Ӧ��ҳĿ¼���ҳ����Ӷ������Ƶ�ҳĿ¼��ҳ����Ӧ
// ��ԭ�����ڴ�ҳ����������ҳ��ӳ�������ʹ�á�����ʱ����������ҳ���������ҳ����
// ԭ�����ڴ��������������˺��������̣������̺����ӽ��̣��������ڴ�����ֱ����һ��
// ����ִ��д����ʱ���ں˲Ż�Ϊд�������̷����µ��ڴ�ҳ��дʱ���ƻ��ƣ���
// ����from��to �����Ե�ַ��size����Ҫ���ƣ����������ڴ泤�ȣ���λ���ֽڡ�
118 int copy_page_tables(unsigned long from,unsigned long to,long size)
119 {
120 unsigned long * from_page_table;
121 unsigned long * to_page_table;
122 unsigned long this_page;
123 unsigned long * from_dir, * to_dir;
124 unsigned long new_page;
125 unsigned long nr;
126
// ���ȼ�����������Դ��ַfrom��Ŀ�ĵ�ַto����Ч�ԡ�Դ��ַ��Ŀ�ĵ�ַ����Ҫ��4Mb
// �ڴ�߽��ַ�ϡ����������������������Ҫ������Ϊһ��ҳ����1024��ɹ���4Mb�ڴ档
// Դ��ַ from ��Ŀ�ĵ�ַ to ֻ���������Ҫ����ܱ�֤��һ��ҳ���ĵ�1�ʼ����ҳ��
// �������ҳ����������������Ч�ġ� Ȼ��ȡ��Դ��ַ��Ŀ�ĵ�ַ����ʼĿ¼��ָ��
// ��from_dir��to_dir�����ٸ��ݲ��������ij���size����Ҫ���Ƶ��ڴ��ռ�õ�ҳ����
// ����Ŀ¼���������μ�ǰ���78��79�еĽ��͡�
127 if ((from&0x3fffff) || (to&0x3fffff))
128 panic("copy_page_tables called with wrong alignment");
129 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
130 to_dir = (unsigned long *) ((to>>20) & 0xffc);
131 size = ((unsigned) (size+0x3fffff)) >> 22;
// �ڵõ���Դ��ʼĿ¼��ָ��from_dir��Ŀ����ʼĿ¼��ָ��to_dir�Լ���Ҫ���Ƶ�ҳ��
// ���� size �����濪ʼ��ÿ��ҳĿ¼����������1ҳ�ڴ��������Ӧ��ҳ�������ҿ�ʼ
// ҳ����Ʋ��������Ŀ��Ŀ¼��ָ����ҳ���Ѿ����ڣ�P=1��������������� ���ԴĿ
// ¼����Ч����ָ����ҳ�������ڣ�P=0���������ѭ��������һ��ҳĿ¼�
132 for( ; size-->0 ; from_dir++,to_dir++) {
133 if (1 & *to_dir)
134 panic("copy_page_tables: already exist");
135 if (!(1 & *from_dir))
136 continue;
// ����֤�˵�ǰԴĿ¼���Ŀ��������֮������ȡԴĿ¼����ҳ����ַfrom_page_table��
// Ϊ�˱���Ŀ��Ŀ¼���Ӧ��ҳ������Ҫ�����ڴ���������1ҳ�����ڴ�ҳ�����ȡ����ҳ��
// ����get_free_page() ����0����˵��û�����뵽�����ڴ�ҳ�棬�������ڴ治�������Ƿ�
// ��-1ֵ�˳���
137 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
138 if (!(to_page_table = (unsigned long *) get_free_page()))
139 return -1; /* Out of memory, see freeing */
// ������������Ŀ��Ŀ¼����Ϣ�������3λ��λ������ǰĿ��Ŀ¼�����7����ʾ��Ӧ
// ҳ��ӳ����ڴ�ҳ�����û����ģ����ҿɶ�д�����ڣ�Usr, R/W, Present���� �����U/S
// λ��0����R/W��û�����á���� U/S��1���� R/W��0����ô�������û���Ĵ����ֻ��
// ��ҳ�档���U/S��R/W����λ������ж�д��Ȩ�ޣ���Ȼ����Ե�ǰ������ҳĿ¼���Ӧ
// ��ҳ����������Ҫ���Ƶ�ҳ����������������ں˿ռ䣬����踴��ͷ160ҳ��Ӧ��ҳ����
// ��nr= 160������Ӧ�ڿ�ʼ640KB�����ڴ档������Ҫ����һ��ҳ���е�����1024��ҳ����
// ��nr= 1024������ӳ��4MB�����ڴ档
140 *to_dir = ((unsigned long) to_page_table) | 7;
141 nr = (from==0)?0xA0:1024;
// ��ʱ���ڵ�ǰҳ������ʼѭ������ָ����nr���ڴ�ҳ������ȡ��Դҳ�������ݣ����
// ��ǰԴҳ��û��ʹ�ã�������Ϊ0�������ø��Ƹñ������������һ�
142 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
143 this_page = *from_page_table;
144 if (!this_page)
145 continue;
// ����ñ��������ݣ����������λP=0����ñ����Ӧ��ҳ������ڽ����豸�С���������
// ��1ҳ�ڴ棬���ӽ����豸�ж����ҳ�棨�������豸���еĻ�����Ȼ��ҳ����Ƶ�
// Ŀ��ҳ�����С�����Դҳ��������ָ�����������ڴ�ҳ�������ñ����־Ϊ��ҳ���ࡱ
// ����7��Ȼ�����������һҳ�������λҳ������ R/W ��־��λ1��0��������ҳ����
// ��Ӧ���ڴ�ҳ��ֻ����Ȼ��ҳ����Ƶ�Ŀ��ҳ���С�
146 if (!(1 & this_page)) {
147 if (!(new_page = get_free_page()))
148 return -1;
149 read_swap_page(this_page>>1, (char *) new_page);
150 *to_page_table = this_page;
151 *from_page_table = new_page | (PAGE_DIRTY | 7);
152 continue;
153 }
154 this_page &= ~2;
155 *to_page_table = this_page;
// �����ҳ������ָ����ҳ��ĵ�ַ��1MB���ϣ�����Ҫ�����ڴ�ҳ��ӳ������mem_map[]��
// ���Ǽ���ҳ��ţ�������Ϊ������ҳ��ӳ��������Ӧ�����������ô�����������λ��1MB
// ���µ�ҳ�棬˵�����ں�ҳ�棬��˲���Ҫ��mem_map[]�������á���Ϊ mem_map[]����
// �ڹ������ڴ����е�ҳ��ʹ������� ��˶����ں��ƶ�������0�в��ҵ���fork()����
// ����1ʱ����������init()�������ڴ�ʱ���Ƶ�ҳ�滹��Ȼ�����ں˴��������������
// �ж��е���䲻��ִ�У�����0 ��ҳ����Ȼ������ʱ��д��ֻ�е����� fork() �ĸ�����
// ���봦�����ڴ�����ҳ��λ�ô���1MB��ʱ�Ż�ִ�С����������Ҫ�ڽ��̵���execve()��
// ��װ��ִ�����³������ʱ�Ż���֡�
// 157����京������Դҳ������ָ�ڴ�ҳҲΪֻ������Ϊ���ڿ�ʼ�����������̹����ڴ�
// ���ˡ�������1��������Ҫ����д�����������ͨ��ҳ�쳣д��������Ϊִ��д�����Ľ�
// �̷���1ҳ�¿���ҳ�棬Ҳ������дʱ���ƣ�copy on write��������
156 if (this_page > LOW_MEM) {
157 *from_page_table = this_page; // ��Դҳ����Ҳֻ����
158 this_page -= LOW_MEM;
159 this_page >>= 12;
160 mem_map[this_page]++;
161 }
162 }
163 }
164 invalidate(); // ˢ��ҳ�任���ٻ��塣
165 return 0;
166 }
167
168 /*
169 * This function puts a page in memory at the wanted address.
170 * It returns the physical address of the page gotten, 0 if
171 * out of memory (either when trying to access page-table or
172 * page.)
173 */
/*
* ���溯����һ�ڴ�ҳ����ã�ӳ�䣩��ָ�����Ե�ַ����������ҳ��
* ��������ַ������ڴ治��(�ڷ���ҳ����ҳ��ʱ)����0��
*/
// ��һ�����ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������
// ����˵�ǰ����Ե�ַ�ռ���ָ����ַaddress����ҳ��ӳ�䵽���ڴ���ҳ��page�ϡ���Ҫ
// �����������ҳĿ¼���ҳ����������ָ��ҳ�����Ϣ�����ɹ�������ҳ���ַ�� ��
// ����ȱҳ�쳣��C����do_no_page() �л���ô˺���������ȱҳ������쳣�������κ�ȱ
// ҳԵ�ʶ���ҳ������ʱ��������Ҫˢ��CPU��ҳ�任���壨���Translation Lookaside
// Buffer - TLB������ʹҳ�����б�־P����0�ij�1����Ϊ��Чҳ��ᱻ���壬��˵�
// ����һ����Ч��ҳ����ʱ����Ҫˢ�¡��ڴ˾ͱ���Ϊ���õ���Invalidate()������
// ����page�Ƿ�������ڴ�����ijһҳ�棨ҳ֡��ҳ��ָ�룻address�����Ե�ַ��
174 static unsigned long put_page(unsigned long page,unsigned long address)
175 {
176 unsigned long tmp, *page_table;
177
178 /* NOTE !!! This uses the fact that _pg_dir=0 */
/* ע��!!! ����ʹ����ҳĿ¼������ַ_pg_dir=0������ */
179
// �����жϲ������������ڴ�ҳ��page ����Ч�ԡ������ҳ��λ�õ���LOW_MEM��1MB����
// ����ϵͳʵ�ʺ����ڴ�߶� HIGH_MEMORY�������档LOW_MEM �����ڴ��������е���
// С��ʼλ�á���ϵͳ�����ڴ�С�ڻ����6MBʱ�����ڴ�����ʼ��LOW_MEM�����ٲ鿴һ
// �¸� pageҳ���Ƿ����Ѿ������ҳ�棬���ж������ڴ�ҳ��ӳ���ֽ�ͼ mem_map[]����
// Ӧ�ֽ��Ƿ��Ѿ���λ����û�����跢�����档
180 if (page < LOW_MEM || page >= HIGH_MEMORY)
181 printk("Trying to put page %p at %p\n",page,address);
182 if (mem_map[(page-LOW_MEM)>>12] != 1)
183 printk("mem_map disagrees with %p at %p\n",page,address);
// Ȼ����ݲ���ָ�������Ե�ַaddress��������ҳĿ¼���ж�Ӧ��Ŀ¼��ָ�룬������ȡ��
// ����ҳ����ַ�� �����Ŀ¼����Ч��P=1������ָ����ҳ�����ڴ��У������ȡ��ָ��ҳ��
// ��ַ�ŵ�page_table �����С���������һ����ҳ���ҳ��ʹ�ã����ڶ�ӦĿ¼��������Ӧ
// ��־��7 �C User��U/S��R/W����Ȼ��ҳ����ַ�ŵ�page_table�����С�
184 page_table = (unsigned long *) ((address>>20) & 0xffc);
185 if ((*page_table)&1)
186 page_table = (unsigned long *) (0xfffff000 & *page_table);
187 else {
188 if (!(tmp=get_free_page()))
189 return 0;
190 *page_table = tmp | 7;
191 page_table = (unsigned long *) tmp;
192 }
// ������ҵ���ҳ�� page_table ���������ҳ�������ݣ���������ҳ��page�ĵ�ַ�����
// ��ͬʱ��λ3����־��U/S��W/R��P������ҳ������ҳ���е�����ֵ�������Ե�ַλ21 --
// λ12��ɵ�10���ص�ֵ��ÿ��ҳ��������1024�0 -- 0x3ff����
193 page_table[(address>>12) & 0x3ff] = page | 7;
194 /* no need for invalidate */
/* ����Ҫˢ��ҳ�任���ٻ��� */
195 return page; // ��������ҳ���ַ��
196 }
197
198 /*
199 * The previous function doesn't work very well if you also want to mark
200 * the page dirty: exec.c wants this, as it has earlier changed the page,
201 * and we want the dirty-status to be correct (for VM). Thus the same
202 * routine, but this time we mark it dirty too.
203 */
/*
* �����Ҳ������ҳ�����ı�־������һ�����������ò��Ǻܺã�exec.c����
* ��Ҫ�������á���Ϊexec.c�к������ڷ���ҳ��֮ǰ�Ĺ�ҳ�����ݡ�Ϊ��ʵ
* ��VM��������Ҫ����ȷ��������״̬��־����������������������ͬ�ĺ�
* �������Ǹú����ڷ���ҳ��ʱ���ҳ���־Ϊ����״̬��
*/
// ��һ�������Ĺ��������ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������
// �ú�������һ������put_page()������ȫһ�������˱�������223������ҳ��������ʱ��
// ͬʱ��������ҳ�����ı�־��λ6��PAGE_DIRTY����
204 unsigned long put_dirty_page(unsigned long page, unsigned long address)
205 {
206 unsigned long tmp, *page_table;
207
208 /* NOTE !!! This uses the fact that _pg_dir=0 */
209
210 if (page < LOW_MEM || page >= HIGH_MEMORY)
211 printk("Trying to put page %p at %p\n",page,address);
212 if (mem_map[(page-LOW_MEM)>>12] != 1)
213 printk("mem_map disagrees with %p at %p\n",page,address);
214 page_table = (unsigned long *) ((address>>20) & 0xffc);
215 if ((*page_table)&1)
216 page_table = (unsigned long *) (0xfffff000 & *page_table);
217 else {
218 if (!(tmp=get_free_page()))
219 return 0;
220 *page_table = tmp|7;
221 page_table = (unsigned long *) tmp;
222 }
223 page_table[(address>>12) & 0x3ff] = page | (PAGE_DIRTY | 7);
224 /* no need for invalidate */
225 return page;
226 }
227
//// ȡ��д����ҳ�溯��������ҳ�쳣�жϹ�����д�����쳣�Ĵ�����дʱ���ƣ���
// ���ں˴�������ʱ���½����븸���̱����óɹ�������������ڴ�ҳ�棬����������Щҳ��
// �������ó�ֻ��ҳ�档�����½��̻�ԭ������Ҫ���ڴ�ҳ��д����ʱ��CPU �ͻ�����
// ���������ҳ��д�����쳣������������������ں˾ͻ������ж�Ҫд��ҳ���Ƿ�����
// ��û�����ҳ�����óɿ�дȻ���˳�����ҳ���dz��ڹ���״̬������Ҫ��������һ��ҳ�沢
// ���Ʊ�дҳ�����ݣ��Թ�д���̵���ʹ�á�������ȡ����
// �������Ϊҳ����ָ�룬��������ַ��[ un_wp_page -- Un-Write Protect Page]
228 void un_wp_page(unsigned long * table_entry)
229 {
230 unsigned long old_page,new_page;
231
// ����ȡ����ָ����ҳ����������ҳ��λ�ã���ַ�����жϸ�ҳ���Ƿ��ǹ���ҳ�档���ԭ
// ҳ���ַ�����ڴ�Ͷ� LOW_MEM����ʾ�����ڴ����У�����������ҳ��ӳ���ֽ�ͼ������
// ֵΪ1����ʾҳ���������1�Σ�ҳ��û�б������������ڸ�ҳ���ҳ�������� R/W ��־
// ����д������ˢ��ҳ�任���ٻ��壬Ȼ�ء���������ڴ�ҳ���ʱֻ��һ������ʹ�ã�
// ���Ҳ����ں��еĽ��̣���ֱ�Ӱ����Ը�Ϊ��д���ɣ���������������һ����ҳ�档
232 old_page = 0xfffff000 & *table_entry; // ȡָ��ҳ����������ҳ���ַ��
233 if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {
234 *table_entry |= 2;
235 invalidate();
236 return;
237 }
// �������Ҫ�����ڴ���������һҳ����ҳ���ִ��д�����Ľ��̵���ʹ�ã�ȡ��ҳ�湲����
// ���ԭҳ������ڴ�Ͷˣ�����ζ�� mem_map[] > 1��ҳ���ǹ����ģ�����ԭҳ���ҳ
// ��ӳ���ֽ�����ֵ�ݼ�1��Ȼ��ָ��ҳ�������ݸ���Ϊ��ҳ���ַ�����ÿɶ�д�ȱ�־
// ��U/S��R/W��P������ˢ��ҳ�任���ٻ���֮�����ԭҳ�����ݸ��Ƶ���ҳ�档
238 if (!(new_page=get_free_page()))
239 oom(); // Out of Memory���ڴ治��������
240 if (old_page >= LOW_MEM)
241 mem_map[MAP_NR(old_page)]--;
242 copy_page(old_page,new_page);
243 *table_entry = new_page | 7;
244 invalidate();
245 }
246
247 /*
248 * This routine handles present pages, when users try to write
249 * to a shared page. It is done by copying the page to a new address
250 * and decrementing the shared-page counter for the old page.
251 *
252 * If it's in code space we exit with a segment error.
253 */
/*
* ���û���ͼ��һ����ҳ����дʱ���ú��������Ѵ��ڵ��ڴ�ҳ�棨дʱ���ƣ���
* ����ͨ����ҳ�渴�Ƶ�һ���µ�ַ�ϲ��ҵݼ�ԭҳ��Ĺ�������ֵʵ�ֵġ�
*
* ������ڴ���ռ䣬���Ǿ���ʾ�γ�����Ϣ���˳���
*/
//// ִ��д����ҳ�洦����
// ��д����ҳ�洦����������ҳ�쳣�жϴ��������е��õ�C��������page.s�����б����á�
// ��������error_code �� address �ǽ�����дд����ҳ��ʱ�� CPU�����쳣���Զ����ɵġ�
// error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���
// �쳣��ҳ�����Ե�ַ��д����ҳ��ʱ�踴��ҳ�棨дʱ���ƣ���
254 void do_wp_page(unsigned long error_code,unsigned long address)
255 {
// �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address
// С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����
// �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ
// ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������
// �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���
256 if (address < TASK_SIZE)
257 printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");
258 if (address - current->start_code > TASK_SIZE) {
259 printk("Bad things happen: page error in do_wp_page\n\r");
260 do_exit(SIGSEGV);
261 }
262 #if 0
263 /* we cannot do this yet: the estdio library writes to code space */
264 /* stupid, stupid. I really want the libc.a from GNU */
/* �������ڻ���������������Ϊestdio����ڴ���ռ�ִ��д���� */
/* ����̫���ˡ��������GNU�õ�libc.a�⡣*/
// ������Ե�ַλ�ڽ��̵Ĵ���ռ��У�����ִֹ�г�����Ϊ������ֻ���ġ�
265 if (CODE_SPACE(address))
266 do_exit(SIGSEGV);
267 #endif
// �������溯��un_wp_page()������ȡ��ҳ�汣������������ҪΪ�����ò�����������
// ���Ե�ַaddressָ��ҳ����ҳ���е�ҳ����ָ�룬����㷽���ǣ�
// �� ((address>>10) & 0xffc)������ָ�����Ե�ַ��ҳ������ҳ���е�ƫ�Ƶ�ַ����Ϊ
// �������Ե�ַ�ṹ��(address>>12) ����ҳ�����е���������ÿ��ռ4���ֽڣ���˳�
// 4��(address>>12)<<2 = (address>>10)&0xffc �Ϳɵõ�ҳ�����ڱ��е�ƫ�Ƶ�ַ��
// �����&0xffc�������Ƶ�ַ��Χ��һ��ҳ���ڡ� ����Ϊֻ�ƶ���10λ��������2λ
// �����Ե�ַ��12 λ�е����2λ��ҲӦ���ε��� ��������Ե�ַ��ҳ������ҳ����ƫ
// �Ƶ�ֱַ��һЩ�ı�ʾ������(((address>>12) & 0x3ff)<<2 )��
// �� (0xfffff000 & *((address>>20) &0xffc))������ȡĿ¼����ҳ���ĵ�ֵַ�����У�
// ((address>>20) &0xffc)����ȡ���Ե�ַ�е�Ŀ¼��������Ŀ¼���е�ƫ��λ�á���Ϊ
// address>>22 ��Ŀ¼������ֵ����ÿ��4���ֽڣ���˳���4�� (address>>22)<<2
// = (address>>20) ����ָ������Ŀ¼���е�ƫ�Ƶ�ַ�� &0xffc��������Ŀ¼������ֵ
// �����2λ����Ϊֻ�ƶ���20λ��������2λ��ҳ�����������ݣ�Ӧ�����ε�����
// *((address>>20) &0xffc) ����ȡָ��Ŀ¼���������ж�Ӧҳ����������ַ���������
// 0xffffff000�������ε�ҳĿ¼�������е�һЩ��־λ��Ŀ¼���12λ����ֱ�۱�ʾΪ
// (0xffffff000 & *((unsigned long *) (((address>>22) & 0x3ff)<<2)))��
// �� �ɢ���ҳ������ҳ����ƫ�Ƶ�ַ���� ����Ŀ¼���������ж�Ӧҳ����������ַ����
// �õ�ҳ�����ָ�루������ַ��������Թ�����ҳ����и��ơ�
268 un_wp_page((unsigned long *)
269 (((address>>10) & 0xffc) + (0xfffff000 &
270 *((unsigned long *) ((address>>20) &0xffc)))));
271
272 }
273
//// дҳ����֤��
// ��ҳ�治��д������ҳ�档��fork.c�е�34�б��ڴ���֤ͨ�ú���verify_area()���á�
// ����address��ָ��ҳ����4G�ռ��е����Ե�ַ��
274 void write_verify(unsigned long address)
275 {
276 unsigned long page;
277
// ����ȡָ�����Ե�ַ��Ӧ��ҳĿ¼�����Ŀ¼���еĴ���λ��P���ж�Ŀ¼���Ӧ��ҳ��
// �Ƿ���ڣ�����λP=1?�����������ڣ�P=0���ء�������������Ϊ���ڲ����ڵ�ҳ��û
// �й�����дʱ���ƿ��ԣ�����������Դ˲����ڵ�ҳ��ִ��д����ʱ��ϵͳ�ͻ���Ϊȱҳ��
// ����ȥִ��do_no_page()����Ϊ����ط�ʹ�� put_page()����ӳ��һ������ҳ�档
// ���ų����Ŀ¼����ȡҳ����ַ������ָ��ҳ����ҳ���е�ҳ����ƫ��ֵ���ö�Ӧ��ַ��ҳ
// ����ָ�롣�ڸñ����а����Ÿ������Ե�ַ��Ӧ������ҳ�档
278 if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))
279 return;
280 page &= 0xfffff000;
281 page += ((address>>10) & 0xffc);
// Ȼ���жϸ�ҳ�����е�λ1��R/W����λ0��P����־�������ҳ�治��д��R/W=0���Ҵ��ڣ�
// ��ô��ִ�й����������ҳ�������дʱ���ƣ�������ʲôҲ������ֱ���˳���
282 if ((3 & *(unsigned long *) page) == 1) /* non-writeable, present */
283 un_wp_page((unsigned long *) page);
284 return;
285 }
286
//// ȡ��һҳ�����ڴ�ҳ��ӳ�䵽ָ�����Ե�ַ����
// get_free_page()��������ȡ�������ڴ�����һҳ�����ڴ档�����������ǻ�ȡ��һҳ
// �����ڴ�ҳ�棬����һ������put_page()��������ҳ��ӳ�䵽ָ�������Ե�ַ����
// ����address��ָ��ҳ������Ե�ַ��
287 void get_empty_page(unsigned long address)
288 {
289 unsigned long tmp;
290
// ������ȡ��һ����ҳ�棬���߲��ܽ���ȡҳ����õ�ָ����ַ��������ʾ�ڴ治������Ϣ��
// 292����Ӣ��ע�͵ĺ����ǣ�free_page()�����IJ���tmp��0Ҳû�й�ϵ���ú��������
// �������������ء�
291 if (!(tmp=get_free_page()) || !put_page(tmp,address)) {
292 free_page(tmp); /* 0 is ok - ignored */
293 oom();
294 }
295 }
296
297 /*
298 * try_to_share() checks the page at address "address" in the task "p",
299 * to see if it exists, and if it is clean. If so, share it with the current
300 * task.
301 *
302 * NOTE! This assumes we have checked that p != current, and that they
303 * share the same executable or library.
304 */
/*
* try_to_share()������"p"�м��λ�ڵ�ַ"address"����ҳ�棬��ҳ���Ƿ���ڣ�
* �Ƿ�ɾ�������Ǹɾ��Ļ������뵱ǰ��������
*
* ע�⣡���������Ѽٶ�p !=��ǰ���������ǹ���ͬһ��ִ�г��������
*/
//// ���ԶԵ�ǰ����ָ����ַ����ҳ����й���������
// ��ǰ���������p��ͬһִ�д��룬Ҳ������Ϊ��ǰ��������p����ִ��fork����������
// ���̣�������ǵĴ�������һ�������δ�����ݶ�������������ô���ݶ�����ҲӦһ����
// ���� address �ǽ����е�����ַ�����ǵ�ǰ�������� p ���̹���ҳ�����ҳ���ַ��
// ����p�ǽ�������ҳ��Ľ��̡����p����address����ҳ����ڲ���û�б��Ĺ��Ļ���
// ���õ�ǰ������p���̹���֮��ͬʱ����Ҫ��ָ֤���ĵ�ַ���Ƿ��Ѿ�������ҳ�棬����
// ����������������أ�1 - ҳ�湲�������ɹ���0 - ʧ�ܡ�
305 static int try_to_share(unsigned long address, struct task_struct * p)
306 {
307 unsigned long from;
308 unsigned long to;
309 unsigned long from_page;
310 unsigned long to_page;
311 unsigned long phys_addr;
312
// ���ȷֱ����ָ������p�к͵�ǰ����������ַaddress��Ӧ��ҳĿ¼�Ϊ�˼��㷽��
// �����ָ������ַaddress����'��'ҳĿ¼��ţ����Խ��̿ռ䣨0 - 64MB�������ҳ
// Ŀ¼��š���'��'ҳĿ¼��ż��Ͻ���p ��CPU 4G���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼�
// ���õ�����p�е�ַ address ��ҳ������Ӧ��4G ���Կռ��е�ʵ��ҳĿ¼��from_page��
// ��'��'ҳĿ¼��ż��ϵ�ǰ����CPU 4G ���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼��������
// �õ���ǰ�����е�ַaddress��ҳ������Ӧ��4G���Կռ��е�ʵ��ҳĿ¼��to_page��
313 from_page = to_page = ((address>>20) & 0xffc);
314 from_page += ((p->start_code>>20) & 0xffc); // p����Ŀ¼�
315 to_page += ((current->start_code>>20) & 0xffc); // ��ǰ����Ŀ¼�
// �ڵõ�p���̺͵�ǰ����address��Ӧ��Ŀ¼�������ֱ�Խ���p�͵�ǰ���̽��д�����
// �������ȶ�p���̵ı�����в�����Ŀ����ȡ��p������ address��Ӧ�������ڴ�ҳ���ַ��
// ���Ҹ�����ҳ����ڣ����Ҹɾ���û�б��Ĺ������ࣩ��
// ��������ȡĿ¼�����ݡ������Ŀ¼����Ч��P=0������ʾĿ¼���Ӧ�Ķ���ҳ�������ڣ�
// ���Ƿ��ء�����ȡ��Ŀ¼���Ӧҳ����ַfrom���Ӷ����������ַaddress��Ӧ��ҳ����
// ָ�룬��ȡ����ҳ����������ʱ������phys_addr�С�
316 /* is there a page-directory at from? */
/* ��from���Ƿ����ҳĿ¼�*/
317 from = *(unsigned long *) from_page; // p����Ŀ¼�����ݡ�
318 if (!(from & 1))
319 return 0;
320 from &= 0xfffff000; // ҳ����ַ��
321 from_page = from + ((address>>10) & 0xffc); // ҳ����ָ�롣
322 phys_addr = *(unsigned long *) from_page; // ҳ�������ݡ�
// ���ſ���ҳ����ӳ�������ҳ���Ƿ���ڲ��Ҹɾ��� 0x41 ��Ӧҳ�����е�D��Dirty����
// P��Present����־�����ҳ�治�ɾ�����Ч�ء�Ȼ�����ǴӸñ�����ȡ������ҳ���ַ
// �ٱ�����phys_addr�С���������ټ��һ���������ҳ���ַ����Ч�ԣ�������Ӧ�ó���
// �������������ֵַ��Ҳ��Ӧ��С���ڴ�Ͷ�(1MB)��
323 /* is the page clean and present? */
/* ����ҳ��ɾ����Ҵ�����*/
324 if ((phys_addr & 0x41) != 0x01)
325 return 0;
326 phys_addr &= 0xfffff000; // ����ҳ���ַ��
327 if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)
328 return 0;
// �������ȶԵ�ǰ���̵ı�����в�����Ŀ����ȡ�õ�ǰ������address��Ӧ��ҳ�����ַ��
// ���Ҹ�ҳ���û��ӳ������ҳ�棬����P=0��
// ����ȡ��ǰ����ҳĿ¼��������to�������Ŀ¼����Ч��P=0������Ŀ¼���Ӧ�Ķ���ҳ��
// �����ڣ�������һ����ҳ�������ҳ����������Ŀ¼��to_page���ݣ�����ָ����ڴ�ҳ�档
329 to = *(unsigned long *) to_page; // ��ǰ����Ŀ¼�����ݡ�
330 if (!(to & 1))
331 if (to = get_free_page())
332 *(unsigned long *) to_page = to | 7;
333 else
334 oom();
// ����ȡĿ¼���е�ҳ����ַ��to������ҳ��������ֵ<<2����ҳ�����ڱ���ƫ�Ƶ�ַ���õ�
// ҳ�����ַ��to_page����Ը�ҳ��������ʱ���Ǽ������Ӧ������ҳ���Ѿ����ڣ�
// ��ҳ����Ĵ���λP=1����˵��ԭ�������빲������p�ж�Ӧ������ҳ�棬�����������Լ�
// �Ѿ�ռ���ˣ�ӳ���У�����ҳ�档����˵���ں˳�����������
335 to &= 0xfffff000; // ҳ����ַ��
336 to_page = to + ((address>>10) & 0xffc); // ҳ�����ַ��
337 if (1 & *(unsigned long *) to_page)
338 panic("try_to_share: to_page already exists");
// ���ҵ��˽���p������ַaddress����Ӧ�ĸɾ����Ҵ��ڵ�����ҳ�棬����Ҳȷ���˵�ǰ
// ����������ַ address ����Ӧ�Ķ���ҳ�����ַ֮���������ڶ����ǽ��й���������
// �����ܼ��������ȶ�p���̵�ҳ��������ģ�������д������R/W=0��ֻ������־��
// Ȼ���õ�ǰ���̸��� p���̵����ҳ�����ʱ��ǰ��������ַ address ��ҳ�漴��
// ӳ�䵽p��������ַaddress��ҳ��ӳ�������ҳ���ϡ�
339 /* share them: write-protect */
/* �����ǽ��й���������д���� */
340 *(unsigned long *) from_page &= ~2;
341 *(unsigned long *) to_page = *(unsigned long *) from_page;
// ���ˢ��ҳ�任���ٻ��塣��������������ҳ���ҳ��ţ�������Ӧҳ��ӳ���ֽ���������
// �����õ���1�����1����ʾ���������ɹ���
342 invalidate();
343 phys_addr -= LOW_MEM;
344 phys_addr >>= 12; // ��ҳ��š�
345 mem_map[phys_addr]++;
346 return 1;
347 }
348
349 /*
350 * share_page() tries to find a process that could share a page with
351 * the current one. Address is the address of the wanted page relative
352 * to the current data space.
353 *
354 * We first check if it is at all feasible by checking executable->i_count.
355 * It should be >1 if there are other tasks sharing this inode.
356 */
/*
* share_page()��ͼ�ҵ�һ�����̣��������뵱ǰ���̹���ҳ�档����address��
* ��ǰ�������ݿռ�������������ijҳ���ַ��
*
* ��������ͨ�����executable->i_count����֤�Ƿ���С���������������ѹ���
* ��inode������Ӧ�ô���1��
*/
//// ����ҳ�洦����
// �ڷ���ȱҳ�쳣ʱ�����ȿ����ܷ�������ͬһ��ִ���ļ����������̽���ҳ�湲��������
// �ú��������ж�ϵͳ���Ƿ�����һ������Ҳ�����е�ǰ����һ����ִ���ļ������У�����
// ϵͳ��ǰ����������Ѱ���������������ҵ�������������ͳ������乲��ָ����ַ����
// ҳ�档��ϵͳ��û�������������������뵱ǰ������ͬ��ִ���ļ�����ô����ҳ�������
// ǰ�����������ڣ���˺��������˳����ж�ϵͳ���Ƿ�����һ������Ҳ��ִ��ͬһ��ִ��
// �ļ��ķ��������ý����������ݽṹ�е� executable �ֶΣ���library�ֶΣ������ֶ�
// ָ���������ִ�г���ʹ�õĿ��ļ������ڴ��е� i�ڵ㡣���ݸ� i�ڵ�����ô���
// i_count ���ǿ��Խ��������жϡ� ���ڵ��i_countֵ����1�������ϵͳ������������
// ��������ͬһ��ִ���ļ�������ļ��������ǿ����ٶ�����ṹ��������������Ƚ��Ƿ�
// ����ͬ�� executable�ֶΣ��� library�ֶΣ������ȷ�����������������ִͬ���ļ�
// �������
// ����inode�������й���ҳ�����ִ���ļ����ڴ�i�ڵ㡣address�ǽ����е�����ַ��
// ���ǵ�ǰ��������p���̹���ҳ�����ҳ���ַ������1 �C���������ɹ���0 - ʧ�ܡ�
357 static int share_page(struct m_inode * inode, unsigned long address)
358 {
359 struct task_struct ** p;
360
// ���ȼ��һ�²���ָ�����ڴ� i�ڵ����ü���ֵ��������ڴ� i�ڵ�����ü���ֵ����
// 1��executable->i_count =1������i�ڵ�ָ��գ���ʾ��ǰϵͳ��ֻ��1������������
// ��ִ���ļ������ṩ��i�ڵ���Ч������������ԣ�ֱ���˳�������
361 if (inode->i_count < 2 || !inode)
362 return 0;
// ��������������������������Ѱ���뵱ǰ���̿ɹ���ҳ��Ľ��̣���������ִͬ���ļ�
// ����һ�����̣������Զ�ָ����ַ��ҳ����й���������������ַaddressС�ڽ��̿�
// �ļ�������ַ�ռ����ʼ��ַLIBRARY_OFFSET�������������ҳ���ڽ���ִ���ļ���Ӧ
// ������ַ�ռ䷶Χ�ڣ����Ǽ��һ��ָ��i�ڵ��Ƿ�����̵�ִ���ļ�i�ڵ㣨������
// ��executable��ͬ��������ͬ�����Ѱ�ҡ�����������ַaddress���ڵ��ڽ��̿��ļ�
// ������ַ�ռ����ʼ��ַLIBRARY_OFFSET���������Ҫ������ҳ���ڽ���ʹ�õĿ��ļ�
// �У����Ǽ��ָ���ڵ� inode �Ƿ�����̵Ŀ��ļ� i�ڵ���ͬ��������ͬ�����Ѱ�ҡ�
// ����ҵ�ij������p����executable��library��ָ���Ľڵ�inode��ͬ�������ҳ��
// ��̽����try_to_share() ����ҳ�湲���������������ɹ�����������1������0��
// ��ʾ����ҳ�����ʧ�ܡ�
363 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
364 if (!*p) // �������������У������Ѱ�ҡ�
365 continue;
366 if (current == *p) // ������ǵ�ǰ����Ҳ����Ѱ�ҡ�
367 continue;
368 if (address < LIBRARY_OFFSET) {
369 if (inode != (*p)->executable) // ����ִ���ļ�i�ڵ㡣
370 continue;
371 } else {
372 if (inode != (*p)->library) // ����ʹ�ÿ��ļ�i�ڵ㡣
373 continue;
374 }
375 if (try_to_share(address,*p)) // ���Թ���ҳ�档
376 return 1;
377 }
378 return 0;
379 }
380
//// ִ��ȱҳ������
// ���ʲ�����ҳ��Ĵ���������ҳ�쳣�жϴ��������е��ô˺�������page.s�����б����á�
// ��������error_code �� address �ǽ����ڷ���ҳ��ʱ�� CPU��ȱҳ�����쳣���Զ����ɡ�
// error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���
// �쳣��ҳ�����Ե�ַ��
// �ú������Ȳ鿴��ȱҳ�Ƿ��ڽ����豸�У����������������������Ѽ��ص���ͬ�ļ�
// ����ҳ�湲��������ֻ�����ڽ��̶�̬�����ڴ�ҳ���ֻ��ӳ��һҳ�����ڴ�ҳ���ɡ�����
// ���������ɹ�����ôֻ�ܴ���Ӧ�ļ��ж�����ȱ������ҳ�浽ָ�����Ե�ַ����
381 void do_no_page(unsigned long error_code,unsigned long address)
382 {
383 int nr[4];
384 unsigned long tmp;
385 unsigned long page;
386 int block,i;
387 struct m_inode * inode;
388
// �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address
// С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����
// �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ
// ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������
// �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���
389 if (address < TASK_SIZE)
390 printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");
391 if (address - current->start_code > TASK_SIZE) {
392 printk("Bad things happen: nonexistent page error in do_no_page\n\r");
393 do_exit(SIGSEGV);
394 }
// Ȼ�����ָ�������Ե�ַaddress������Ӧ�Ķ���ҳ����ָ�룬�����ݸ�ҳ���������ж�
// address����ҳ���Ƿ��ڽ����豸�С����������ҳ�沢�˳�������������ȡָ�����Ե�ַ
// address��Ӧ��Ŀ¼�����ݡ������Ӧ�Ķ���ҳ�����ڣ���ȡ����Ŀ¼���ж���ҳ���ĵ�ַ��
// ����ҳ����ƫ��ֵ���õ����Ե�ַaddress��ҳ���Ӧ��ҳ�����ָ�룬�Ӷ����ҳ������
// �ݡ���ҳ�������ݲ�Ϊ0����ҳ�������λP=0����˵����ҳ����ָ��������ҳ��Ӧ���ڽ�
// ���豸�С����Ǵӽ����豸�е���ָ��ҳ����˳�������
395 page = *(unsigned long *) ((address >> 20) & 0xffc); // ȡĿ¼�����ݡ�
396 if (page & 1) {
397 page &= 0xfffff000; // ����ҳ����ַ��
398 page += (address >> 10) & 0xffc; // ҳ����ָ�롣
399 tmp = *(unsigned long *) page; // ҳ�������ݡ�
400 if (tmp && !(1 & tmp)) {
401 swap_in((unsigned long *) page); // �ӽ����豸��ҳ�档
402 return;
403 }
404 }
// ����ȡ���Կռ���ָ����ַaddress��ҳ���ַ�������ָ�����Ե�ַ�ڽ��̿ռ��������
// ���̻�ַ��ƫ�Ƴ���ֵtmp������Ӧ������ַ���Ӷ��������ȱҳҳ����ִ���ļ�ӳ����
// ���ڿ��ļ��еľ�����ʼ���ݿ�š�
405 address &= 0xfffff000; // address��ȱҳҳ���ַ��
406 tmp = address - current->start_code; // ȱҳҳ���Ӧ����ַ��
// ���ȱҳ��Ӧ������ַtmp���ڿ�ӳ���ļ��ڽ������ռ��е���ʼλ�ã�˵��ȱ�ٵ�ҳ
// ���ڿ�ӳ���ļ��С����Ǵӵ�ǰ�����������ݽṹ�п���ȡ�ÿ�ӳ���ļ���i�ڵ�library��
// ���������ȱҳ�ڿ��ļ��е���ʼ���ݿ��block�����ȱҳ��Ӧ������ַtmpС�ڽ���
// ��ִ��ӳ���ļ�������ַ�ռ��ĩ��λ�ã���˵��ȱ�ٵ�ҳ���ڽ���ִ���ļ�ӳ���У���
// �ǿ��Դӵ�ǰ�����������ݻ�����ȡ��ִ���ļ���i�ڵ��executable�����������ȱҳ
// ��ִ���ļ�ӳ���е���ʼ���ݿ��block��������ַtmp�Ȳ���ִ���ļ�ӳ��ĵ�ַ��Χ
// �ڣ�Ҳ���ڿ��ļ��ռ䷶Χ�ڣ���˵��ȱҳ�ǽ��̷��ʶ�̬������ڴ�ҳ���������£����
// û�ж�Ӧi�ڵ�����ݿ�ţ����ÿգ���
// ��Ϊ���豸�ϴ�ŵ�ִ���ļ�ӳ���1�������dz���ͷ�ṹ������ڶ�ȡ���ļ�ʱ��Ҫ����
// ��1�����ݡ�������Ҫ���ȼ���ȱҳ���ڵ����ݿ�š���Ϊÿ�����ݳ���ΪBLOCK_SIZE =
// 1KB�����һҳ�ڴ�ɴ��4�����ݿ顣��������ַtmp�������ݿ��С�ټ�1���ɵó�
// ȱ�ٵ�ҳ����ִ��ӳ���ļ��е���ʼ���block��
407 if (tmp >= LIBRARY_OFFSET ) {
408 inode = current->library; // ���ļ�i�ڵ��ȱҳ��ʼ��š�
409 block = 1 + (tmp-LIBRARY_OFFSET) / BLOCK_SIZE;
410 } else if (tmp < current->end_data) {
411 inode = current->executable; // ִ���ļ�i�ڵ��ȱҳ��ʼ��š�
412 block = 1 + tmp / BLOCK_SIZE;
413 } else {
414 inode = NULL; // �Ƕ�̬��������ݻ�ջ�ڴ�ҳ�档
415 block = 0;
416 }
// ���ǽ��̷����䶯̬�����ҳ���Ϊ�˴��ջ��Ϣ�������ȱҳ�쳣����ֱ������һҳ��
// ���ڴ�ҳ�沢ӳ�䵽���Ե�ַaddress�����ɡ�����˵����ȱҳ���ڽ���ִ���ļ������
// ����Χ�ڣ����Ǿͳ��Թ���ҳ����������ɹ����˳��������ɹ���ֻ������һҳ�����ڴ�
// ҳ��page��Ȼ����豸�϶�ȡִ���ļ��е���Ӧҳ�沢���ã�ӳ�䣩������ҳ������ַ
// tmp����
417 if (!inode) { // �Ƕ�̬����������ڴ�ҳ�档
418 get_empty_page(address);
419 return;
420 }
421 if (share_page(inode,tmp)) // ��������ַtmp��ҳ��Ĺ�����
422 return;
423 if (!(page = get_free_page())) // ����һҳ�����ڴ档
424 oom();
425 /* remember that 1 block is used for header */
/* ��ס��������ͷҪʹ��1�����ݿ� */
// ���������ź�ִ���ļ���i�ڵ㣬���ǾͿ��Դ�ӳ��λͼ���ҵ���Ӧ���豸�ж�Ӧ���豸
// ����ţ�������nr[]�����У�������bread_page()���ɰ���4��������뵽����ҳ��
// page�С�
426 for (i=0 ; i<4 ; block++,i++)
427 nr[i] = bmap(inode,block);
428 bread_page(page,inode->i_dev,nr);
// �ڶ��豸�������ʱ�����ܻ��������һ�����������ִ���ļ��еĶ�ȡҳ��λ�ÿ�����
// �ļ�β����1��ҳ��ij��ȡ���˾Ϳ��ܶ���һЩ���õ���Ϣ������IJ������ǰ��ⲿ�ֳ�
// ��ִ���ļ�end_data�Ժ�IJ��ֽ������㴦������Ȼ������ҳ����ĩ�˳���1ҳ��˵����
// �Ǵ�ִ���ļ�ӳ���ж�ȡ��ҳ�棬���Ǵӿ��ļ��ж�ȡ�ģ���˲���ִ�����������
429 i = tmp + 4096 - current->end_data; // �������ֽڳ���ֵ��
430 if (i>4095) // ��ĩ�˳���1ҳ�������㡣
431 i = 0;
432 tmp = page + 4096; // tmpָ��ҳ��ĩ�ˡ�
433 while (i-- > 0) { // ҳ��ĩ��i�ֽ����㡣
434 tmp--;
435 *(char *)tmp = 0;
436 }
// ��������ȱҳ�쳣��һҳ����ҳ��ӳ�䵽ָ�����Ե�ַaddress�����������ɹ��ͷ��ء�
// ������ͷ��ڴ�ҳ����ʾ�ڴ治����
437 if (put_page(page,address))
438 return;
439 free_page(page);
440 oom();
441 }
442
//// �����ڴ������ʼ����
// �ú�����1MB�����ڴ�������ҳ��Ϊ��λ���й���ǰ�ij�ʼ�����ù�����һ��ҳ�泤��Ϊ
// 4KB�ֽڡ��ú����� 1MB�������������ڴ滮�ֳ�һ����ҳ�棬��ʹ��һ��ҳ��ӳ���ֽ�
// ����mem_map[] ������������Щҳ�档���ھ���16MB�ڴ������Ļ����������鹲��3840
// �� ((16MB - 1MB)/4KB)�����ɹ���3840������ҳ�档ÿ��һ�������ڴ�ҳ�汻ռ��ʱ��
// �� mem_map[]�ж�Ӧ�ĵ��ֽ�ֵ��1�����ͷ�һ������ҳ�棬�ͰѶ�Ӧ�ֽ�ֵ��1�� ����
// ��ֵΪ 0�����ʾ��Ӧҳ����У� ���ֽ�ֵ���ڻ����1�����ʾ��Ӧҳ�汻ռ�û�
// ͬ������ռ�á�
// �ڸð汾�� Linux�ں��У�����ܹ��� 16MB�������ڴ棬����16MB���ڴ潫���ò��á�
// ���ھ���16MB�ڴ��PC��ϵͳ����û������������ RAMDISK������� start_memͨ��
// ��4MB��end_mem��16MB����˴�ʱ���ڴ�����Χ��4MB��16MB������3072������ҳ���
// �����䡣����Χ0 - 1MB�ڴ�ռ������ں�ϵͳ����ʵ�ں�ֻʹ��0 ��640Kb��ʣ�µIJ�
// �ֱ����ָ��ٻ�����豸�ڴ�ռ�ã���
// ����start_mem�ǿ�����ҳ���������ڴ�����ʼ��ַ����ȥ��RAMDISK��ռ�ڴ�ռ䣩��
// end_mem��ʵ�������ڴ�����ַ������ַ��Χstart_mem��end_mem�����ڴ�����
443 void mem_init(long start_mem, long end_mem)
444 {
445 int i;
446
// ���Ƚ�1MB��16MB��Χ�������ڴ�ҳ���Ӧ���ڴ�ӳ���ֽ���������Ϊ��ռ��״̬������
// ���ֽ�ֵȫ�����ó�USED��100����PAGING_PAGES������Ϊ(PAGING_MEMORY>>12)����1MB
// �������������ڴ��ҳ����ڴ�ҳ����(15MB/4KB = 3840)��
447 HIGH_MEMORY = end_mem; // �����ڴ���߶ˣ�16MB����
448 for (i=0 ; i<PAGING_PAGES ; i++)
449 mem_map[i] = USED;
// Ȼ��������ڴ�����ʼ�ڴ� start_mem ��ҳ���Ӧ�ڴ�ӳ���ֽ����������i�����ڴ���
// ҳ��������ʱ mem_map[] ����ĵ�i������Ӧ���ڴ����е�1��ҳ�档������ڴ�����
// ҳ���Ӧ�����������㣨��ʾ���У������ھ���16MB�����ڴ��ϵͳ��mem_map[] �ж�Ӧ
// 4Mb--16Mb���ڴ���������㡣
450 i = MAP_NR(start_mem); // ���ڴ�����ʼλ�ô�ҳ��š�
451 end_mem -= start_mem;
452 end_mem >>= 12; // ���ڴ����е���ҳ������
453 while (end_mem-->0)
454 mem_map[i++]=0; // ���ڴ���ҳ���Ӧ�ֽ�ֵ���㡣
455 }
456
// ��ʾϵͳ�ڴ���Ϣ��
// �����ڴ�ӳ���ֽ����� mem_map[] �е���Ϣ�Լ�ҳĿ¼��ҳ������ͳ��ϵͳ��ʹ�õ��ڴ�ҳ
// ���������ڴ������������ڴ�ҳ�������ú����� chr_drv/keyboard.S�����186�б����á�
// �������¡�Shift + Scroll Lock����ϼ�ʱ����ʾϵͳ�ڴ�ͳ����Ϣ��
457 void show_mem(void)
458 {
459 int i,j,k,free=0,total=0;
460 int shared=0;
461 unsigned long * pg_tbl;
462
// �����ڴ�ӳ���ֽ�����mem_map[]��ͳ��ϵͳ���ڴ���ҳ������total���Լ����п���ҳ��
// ��free�ͱ�������ҳ����shared������Щ��Ϣ��ʾ��
463 printk("Mem-info:\n\r");
464 for(i=0 ; i<PAGING_PAGES ; i++) {
465 if (mem_map[i] == USED) // 1MB�����ڴ�ϵͳռ�õ�ҳ�档
466 continue;
467 total++;
468 if (!mem_map[i])
469 free++; // ���ڴ�������ҳ��ͳ�ơ�
470 else
471 shared += mem_map[i]-1; // ������ҳ�������ֽ�ֵ>1����
472 }
473 printk("%d free pages of %d\n\r",free,total);
474 printk("%d pages shared\n\r",shared);
// ͳ�ƴ�������ҳ������ҳ������ҳĿ¼��ǰ4��ں˴���ʹ�ã�����Ϊͳ�Ʒ�Χ�����
// ɨ�账����ҳĿ¼��ӵ�5�ʼ��������ѭ����������ҳĿ¼���ǰ4���������Ӧ
// �Ķ���ҳ�����ڣ���ô��ͳ�ƶ���ҳ������ռ�õ��ڴ�ҳ�棨484�У���Ȼ��Ը�ҳ������
// ��ҳ�����Ӧҳ���������ͳ�ơ�
475 k = 0; // һ������ռ��ҳ��ͳ��ֵ��
476 for(i=4 ; i<1024 ;) {
477 if (1&pg_dir[i]) {
// �����ҳĿ¼���Ӧ����ҳ����ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����Ŀ¼��
// �����⡣������ʾ��Ŀ¼����Ϣ������������һ��Ŀ¼���
478 if (pg_dir[i]>HIGH_MEMORY) { // Ŀ¼�����ݲ�������
479 printk("page directory[%d]: %08X\n\r",
480 i,pg_dir[i]);
481 continue; // continue֮ǰ�����i++��
482 }
// ���ҳĿ¼���Ӧ����ҳ���ġ���ַ������LOW_MEM����1MB�������һ������ռ�õ�����
// �ڴ�ҳͳ��ֵk��1����ϵͳռ�õ����������ڴ�ҳͳ��ֵfree��1��Ȼ��ȡ��Ӧҳ����ַ
// pg_tbl�����Ը�ҳ��������ҳ�������ͳ�ơ������ǰҳ������ָ����ҳ����ڲ��Ҹ�����
// ҳ�桰��ַ������LOW_MEM����ô�ͽ�ҳ�����Ӧҳ������ͳ��ֵ��
483 if (pg_dir[i]>LOW_MEM)
484 free++,k++; // ͳ��ҳ��ռ��ҳ�档
485 pg_tbl=(unsigned long *) (0xfffff000 & pg_dir[i]);
486 for(j=0 ; j<1024 ; j++)
487 if ((pg_tbl[j]&1) && pg_tbl[j]>LOW_MEM)
// ����������ҳ���ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����ҳ�������������⣬
// ������ʾ��ҳ�������ݡ�����ҳ�����Ӧҳ������ͳ��ֵ����
488 if (pg_tbl[j]>HIGH_MEMORY)
489 printk("page_dir[%d][%d]: %08X\n\r",
490 i,j, pg_tbl[j]);
491 else
492 k++,free++; // ͳ��ҳ�����Ӧҳ�档
493 }
// ��ÿ���������Կռ䳤����64MB������һ������ռ��16��Ŀ¼��������ÿͳ����16��
// Ŀ¼��Ͱѽ��̵�����ṹռ�õ�ҳ��ͳ�ƽ���������ʱk=0���ʾ��ǰ��16��ҳĿ¼����
// Ӧ�Ľ�����ϵͳ�в����ڣ�û�д��������Ѿ���ֹ���� ����ʾ�˶�Ӧ���̺ź���ռ�õ�����
// �ڴ�ҳͳ��ֵk��k���㣬������ͳ����һ������ռ�õ��ڴ�ҳ������
494 i++;
495 if (!(i&15) && k) { // k !=0 ��ʾ��Ӧ���̴��ڡ�
496 k++,free++; /* one page/process for task_struct */
497 printk("Process %d: %d pages\n\r",(i>>4)-1,k);
498 k = 0;
499 }
500 }
// �����ʾϵͳ������ʹ�õ��ڴ�ҳ������ڴ������ܵ��ڴ�ҳ������
501 printk("Memory found: %d (%d)\n\r",free-shared,total);
502 }
503
1 /*
2 * linux/mm/page.s
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * page.s contains the low-level page-exception code.
9 * the real work is done in mm.c
10 */
/*
* page.s��������ײ�ҳ�쳣�������롣ʵ�ʹ�����memory.c����ɡ�
*/
11
12 .globl _page_fault # ����Ϊȫ�ֱ���������traps.c����������ҳ�쳣��������
13
14 _page_fault:
15 xchgl %eax,(%esp) # ȡ�����뵽eax��
16 pushl %ecx
17 pushl %edx
18 push %ds
19 push %es
20 push %fs
21 movl $0x10,%edx # ���ں����ݶ�ѡ�����
22 mov %dx,%ds
23 mov %dx,%es
24 mov %dx,%fs
25 movl %cr2,%edx # ȡ����ҳ���쳣�����Ե�ַ��
26 pushl %edx # �������Ե�ַ�ͳ�����ѹ��ջ�У���Ϊ�����ú����IJ�����
27 pushl %eax
28 testl $1,%eax # ����ҳ���ڱ�־P��λ0�����������ȱҳ������쳣����ת��
29 jne 1f
30 call _do_no_page # ����ȱҳ����������mm/memory.c,365�У���
31 jmp 2f
32 1: call _do_wp_page # �����������������mm/memory.c,247����
33 2: addl $8,%esp # ����ѹ��ջ����������������ջ�мĴ������˳��жϡ�
34 pop %fs
35 pop %es
36 pop %ds
37 popl %edx
38 popl %ecx
39 popl %eax
40 iret
1 /*
2 * linux/mm/swap.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This file should contain most things doing the swapping from/to disk.
9 * Started 18.12.91
10 */
/*
* ������Ӧ�ð�������ִ���ڴ潻���Ĵ��루���ڴ浽���̻�֮����
* ��91��12��18�տ�ʼ���ơ�
*/
11
12 #include <string.h> // �ַ���ͷ�ļ���������һЩ�й��ڴ���ַ���������Ƕ�뺯����
13
14 #include <linux/mm.h> // �ڴ����ͷ�ļ�������ҳ�泤�ȣ���һЩ�ڴ��������ԭ�͡�
15 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
16 #include <linux/head.h> // headͷ�ļ��������˶��������ļṹ���ͼ���ѡ���������
17 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�Ͷ��塣
18
// ÿ���ֽ�8λ�����1ҳ��4096�ֽڣ�����32768������λ����1������λ��Ӧ1ҳ�ڴ棬
// �����ɹ���32768��ҳ�棬��Ӧ128MB�ڴ�������
19 #define SWAP_BITS (4096<<3)
20
// ����λ�����ꡣͨ��������ͬ��"op"���ɶ����ָ������λ���в��ԡ����û�������ֲ�����
// ����addr��ָ�����Ե�ַ��nr��ָ����ַ����ʼ�ı���λƫ��λ���ú�Ѹ�����ַaddr��
// ��nr������λ��ֵ�����λ��־�����û�λ�ñ���λ�����ؽ�λ��־ֵ����ԭ����λֵ����
// ��25���ϵ�һ��ָ����"op"�ַ��IJ�ͬ������γɲ�ͬ��ָ�
// ��"op"= ""ʱ������ָ��bt �C ��Bit Test�����Բ���ԭֵ���ý�λλ��
// ��"op"="s"ʱ������ָ��bts - ��Bit Test and Set�����ñ���λֵ����ԭֵ���ý�λλ��
// ��"op"="r"ʱ������ָ��btr - ��Bit Test and Reset����λ����λֵ��ԭֵ���ý�λλ��
// ���룺%0 �C ������ֵ)��%1 -λƫ��(nr)��%2 �C��ַ(addr)��%3 �C �Ӳ����Ĵ�����ֵ(0)��
// ��Ƕ������ѻ���ַ��%2���ͱ���ƫ��ֵ��%1����ָ���ı���λֵ�ȱ��浽��λ��־CF�У�
// Ȼ�����ã���λ���ñ���λ��ָ��adcl�Ǵ���λλ�ӣ����ڸ��ݽ�λλCF���ò�������%0����
// ���CF = 1 �ؼĴ���ֵ = 1�����ؼĴ���ֵ = 0 ��
21 #define bitop(name,op) \
22 static inline int name(char * addr,unsigned int nr) \
23 { \
24 int __res; \
25 __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
26 :"=g" (__res) \
27 :"r" (nr),"m" (*(addr)),"0" (0)); \
28 return __res; \
29 }
30
// ������ݲ�ͬ��op�ַ�����3����Ƕ������
31 bitop(bit,"") // ������Ƕ���� bit(char * addr, unsigned int nr)��
32 bitop(setbit,"s") // ������Ƕ���� setbit(char * addr, unsigned int nr)��
33 bitop(clrbit,"r") // ������Ƕ���� clrbit(char * addr, unsigned int nr)��
34
35 static char * swap_bitmap = NULL;
36 int SWAP_DEV = 0; // �ں˳�ʼ��ʱ���õĽ����豸�š�
37
38 /*
39 * We never page the pages in task[0] - kernel memory.
40 * We page all other pages.
41 */
/*
* ���ǴӲ���������0��task[0]����ҳ�� �C ���������ں�ҳ�档
* ����ֻ������ҳ����н���������
*/
// ��1�������ڴ�ҳ�档��������0ĩ�ˣ�64MB������ʼ�������ڴ�ҳ�档
42 #define FIRST_VM_PAGE (TASK_SIZE>>12) // = 64MB/4KB = 16384��
43 #define LAST_VM_PAGE (1024*1024) // = 4GB/4KB = 1048576��
44 #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE) // = 1032192����0��ʼ�ƣ���
45
// ����1ҳ����ҳ�档
// ɨ����������ӳ��λͼ������Ӧλͼ������λ0���⣩������ֵΪ1�ĵ�һ������λ�ţ�
// ��Ŀǰ���еĽ���ҳ��š��������ɹ��ؽ���ҳ��ţ�����0��
46 static int get_swap_page(void)
47 {
48 int nr;
49
50 if (!swap_bitmap)
51 return 0;
52 for (nr = 1; nr < 32768 ; nr++)
53 if (clrbit(swap_bitmap,nr))
54 return nr; // ����Ŀǰ���еĽ���ҳ��š�
55 return 0;
56 }
57
// �ͷŽ����豸��ָ���Ľ���ҳ�档
// �ڽ���λͼ������ָ��ҳ��Ŷ�Ӧ�ı���λ����1������ԭ���ñ���λ�͵���1�����ʾ
// �����豸��ԭ����ҳ���û�б�ռ�ã�����λͼ������������ʾ������Ϣ�����ء�
// ����ָ������ҳ��š�
58 void swap_free(int swap_nr)
59 {
60 if (!swap_nr)
61 return;
62 if (swap_bitmap && swap_nr < SWAP_BITS)
63 if (!setbit(swap_bitmap,swap_nr))
64 return;
65 printk("Swap-space bad (swap_free())\n\r");
66 return;
67 }
68
// ��ָ��ҳ�潻�����ڴ��С�
// ��ָ��ҳ����Ķ�Ӧҳ��ӽ����豸�ж��뵽��������ڴ�ҳ���С��Ľ���λͼ�ж�Ӧ
// ����λ����λ����ͬʱ��ҳ�������ݣ�����ָ����ڴ�ҳ�棬��������Ӧ��־��
69 void swap_in(unsigned long *table_ptr)
70 {
71 int swap_nr;
72 unsigned long page;
73
// ���ȼ�齻��λͼ�Ͳ�����Ч�ԡ��������λͼ�����ڣ�����ָ��ҳ�����Ӧ��ҳ���Ѵ���
// ���ڴ��У����߽���ҳ���Ϊ 0������ʾ������Ϣ���˳��������ѷŵ������豸��ȥ���ڴ�
// ҳ�棬��Ӧҳ�����д�ŵ�Ӧ�ǽ���ҳ���*2����(swap_nr << 1)���μ�����Գ��Խ�����
// ��try_to_swap_out()�е�111�е�˵����
74 if (!swap_bitmap) {
75 printk("Trying to swap in without swap bit-map");
76 return;
77 }
78 if (1 & *table_ptr) {
79 printk("trying to swap in present page\n\r");
80 return;
81 }
82 swap_nr = *table_ptr >> 1;
83 if (!swap_nr) {
84 printk("No swap page in swap_in\n\r");
85 return;
86 }
// Ȼ������һҳ�����ڴ沢�ӽ����豸�ж���ҳ���Ϊswap_nr��ҳ�档�ڰ�ҳ�潻������
// �Ͱѽ���λͼ�ж�Ӧ����λ��λ�������ԭ��������λ�ģ�˵���˴����ٴδӽ�����
// ���ж�����ͬ��ҳ�棬������ʾһ�¾�����Ϣ�������ҳ����ָ�������ҳ�棬������ҳ
// �����ġ��û��ɶ�д�ʹ��ڱ�־��Dirty��U/S��R/W��P����
87 if (!(page = get_free_page()))
88 oom();
89 read_swap_page(swap_nr, (char *) page); // ��include/linux/mm.h�ж��塣
90 if (setbit(swap_bitmap,swap_nr))
91 printk("swapping in multiply from same page\n\r");
92 *table_ptr = page | (PAGE_DIRTY | 7);
93 }
94
// ����ҳ�潻����ȥ��
// ��ҳ��û�б��Ĺ����ñ����ڽ����豸�У���Ϊ��Ӧҳ�滹������ֱ�Ӵ���Ӧӳ���ļ�
// �ж��롣���ǿ���ֱ���ͷŵ���Ӧ����ҳ�����¡����������һ������ҳ��ţ�Ȼ���ҳ��
// ������ȥ����ʱ����ҳ���Ҫ�����ڶ�Ӧҳ�����У���������Ҫ����ҳ�������λP = 0��
// ������ҳ����ָ�롣ҳ�潻�����ͷųɹ�����1������0��
95 int try_to_swap_out(unsigned long * table_ptr)
96 {
97 unsigned long page;
98 unsigned long swap_nr;
99
// �����жϲ�������Ч�ԡ�����Ҫ������ȥ���ڴ�ҳ�沢�����ڣ������Ч�������˳���
// ��ҳ����ָ��������ҳ���ַ���ڷ�ҳ�������ڴ�߶�PAGING_MEMORY��15MB����Ҳ�˳���
100 page = *table_ptr;
101 if (!(PAGE_PRESENT & page))
102 return 0;
103 if (page - LOW_MEM > PAGING_MEMORY)
104 return 0;
// ���ڴ�ҳ���ѱ��Ĺ������Ǹ�ҳ���DZ������ģ���ôΪ���������Ч�ʣ�����ҳ�治��
// ��������ȥ������ֱ���˳�����������0�����������һ����ҳ��ţ�������������ҳ��
// ���У�Ȼ���ҳ�潻����ȥ���ͷŶ�Ӧ�����ڴ�ҳ�档
105 if (PAGE_DIRTY & page) {
106 page &= 0xfffff000; // ȡ����ҳ���ַ��
107 if (mem_map[MAP_NR(page)] != 1)
108 return 0;
109 if (!(swap_nr = get_swap_page())) // ���뽻��ҳ��š�
110 return 0;
// ����Ҫ�������豸�е�ҳ�棬��Ӧҳ�����н���ŵ���(swap_nr << 1)�� ��2������1λ��
// ��Ϊ�˿ճ�ԭ��ҳ����Ĵ���λ��P����ֻ�д���λP=0����ҳ�������ݲ�Ϊ0��ҳ��Ż�
// �ڽ����豸�С� Intel�ֲ�����ȷָ������һ������Ĵ���λ P = 0ʱ����Чҳ�����
// ��������λ��λ31��1���ɹ�����ʹ�á�����д����ҳ����write_swap_page(nr, buffer)
// ������Ϊll_rw_page(WRITE,SWAP_DEV,(nr),(buffer))���μ�linux/mm.h �ļ���12�С�
111 *table_ptr = swap_nr<<1;
112 invalidate(); // ˢ��CPUҳ�任���ٻ��塣
113 write_swap_page(swap_nr, (char *) page);
114 free_page(page);
115 return 1;
116 }
// �������ҳ��û���Ĺ�����ô�Ͳ��ý�����ȥ����ֱ���ͷż��ɡ�
117 *table_ptr = 0;
118 invalidate();
119 free_page(page);
120 return 1;
121 }
122
123 /*
124 * Ok, this has a rather intricate logic - the idea is to make good
125 * and fast machine code. If we didn't worry about that, things would
126 * be easier.
127 */
/*
* OK�������������һ���dz����ӵ��� �C ���ڲ������Ժò����ٶȿ��
* �����롣������Dz��Դ˲��ĵĻ�����ô������ܸ�����Щ��
*/
// ���ڴ�ҳ��ŵ������豸�С�
// �����Ե�ַ64MB��Ӧ��Ŀ¼�FIRST_VM_PAGE>>10����ʼ����������4GB���Կռ䣬����
// ЧҳĿ¼����ҳ����ҳ����ָ���������ڴ�ҳ��ִ�н����������豸��ȥ�ij��ԡ�һ���ɹ�
// �ػ���һ��ҳ�棬�ͷ���1������0���ú�������get_free_page()�б����á�
128 int swap_out(void)
129 {
130 static int dir_entry = FIRST_VM_PAGE>>10; // ������1�ĵ�1��Ŀ¼��������
131 static int page_entry = -1;
132 int counter = VM_PAGES;
133 int pg_table;
134
// ��������ҳĿ¼�������Ҷ���ҳ�����ڵ�ҳĿ¼��pg_table���ҵ����˳�ѭ�����������
// ҳĿ¼������Ӧʣ�����ҳ������counter��Ȼ����������һҳĿ¼� ��ȫ��������
// ��û���ҵ��ʺϵģ����ڵģ�ҳĿ¼������¼���������
135 while (counter>0) {
136 pg_table = pg_dir[dir_entry]; // ҳĿ¼�����ݡ�
137 if (pg_table & 1)
138 break;
139 counter -= 1024; // 1��ҳ����Ӧ1024��ҳ֡��
140 dir_entry++; // ��һĿ¼�
141 if (dir_entry >= 1024)
142 dir_entry = FIRST_VM_PAGE>>10;
143 }
// ��ȡ�õ�ǰĿ¼���ҳ��ָ�����Ը�ҳ���е����� 1024 ��ҳ�棬��һ���ý�������
// try_to_swap_out()���Խ�����ȥ��һ��ij��ҳ��ɹ������������豸�оͷ���1��������
// ��Ŀ¼�������ҳ�����ѳ���ʧ�ܣ�����ʾ�������ڴ����ꡱ�ľ��棬������0��
144 pg_table &= 0xfffff000; // ҳ��ָ�루��ַ����
145 while (counter-- > 0) {
146 page_entry++; // ҳ������������ʼΪ-1����
// ����Ѿ����Դ����굱ǰҳ�������û���ܹ��ɹ��ؽ�����һ��ҳ�棬����ʱҳ��������
// ���ڵ���1024������ͬǰ���135 �C 143��ִ����ͬ�Ĵ�����ѡ��һ������ҳ�����ڵ�ҳ
// Ŀ¼���ȡ����Ӧ����ҳ��ָ�롣
147 if (page_entry >= 1024) {
148 page_entry = 0;
149 repeat:
150 dir_entry++;
151 if (dir_entry >= 1024)
152 dir_entry = FIRST_VM_PAGE>>10;
153 pg_table = pg_dir[dir_entry]; // ҳĿ¼�����ݡ�
154 if (!(pg_table&1))
155 if ((counter -= 1024) > 0)
156 goto repeat;
157 else
158 break;
159 pg_table &= 0xfffff000; // ҳ��ָ�롣
160 }
161 if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
162 return 1;
163 }
164 printk("Out of swap-memory\n\r");
165 return 0;
166 }
167
168 /*
169 * Get physical address of first (actually last :-) free page, and mark it
170 * used. If no free pages left, return 0.
171 */
/*
* ��ȡ��(ʵ���������1��:-)����ҳ�棬�����Ϊ��ʹ�á����û�п���ҳ�棬
* �ͷ���0��
*/
//// �����ڴ���������1ҳ��������ҳ�档
// ����Ѿ�û�п��������ڴ�ҳ�棬�����ִ�н���������Ȼ���ٴ�����ҳ�档
// ���룺%1(ax=0) - 0��%2(LOW_MEM)�ڴ��ֽ�λͼ��������ʼλ�ã�%3(cx= PAGING_PAGES)��
// %4(edi=mem_map+PAGING_PAGES-1)��
// ���������%0��ax = ����ҳ����ʼ��ַ��������������ҳ���������ַ��
// ����%4�Ĵ���ʵ��ָ��mem_map[]�ڴ��ֽ�λͼ�����һ���ֽڡ���������λͼĩ�˿�ʼ��
// ǰɨ������ҳ���־��ҳ������ΪPAGING_PAGES��������ҳ����У��ڴ�λͼ�ֽ�Ϊ0����
// ����ҳ���ַ��ע�⣡������ֻ��ָ�������ڴ�����һҳ��������ҳ�棬����û��ӳ�䵽ij
// �����̵ĵ�ַ�ռ���ȥ������� put_page() ���������ڰ�ָ��ҳ��ӳ�䵽ij�����̵ĵ�ַ
// �ռ��С���Ȼ�����ں�ʹ�ñ�����������Ҫ��ʹ�� put_page() ����ӳ�䣬��Ϊ�ں˴����
// ���ݿռ䣨16MB���Ѿ��Եȵ�ӳ�䵽������ַ�ռ䡣
// ��65�ж�����һ���ֲ��Ĵ����������ñ������������� eax�Ĵ����У��Ա��ڸ�Ч���ʺ�
// ���������ֶ�������ķ�����Ҫ������Ƕ�������С���ϸ˵���μ�gcc�ֲᡰ��ָ���Ĵ�
// ���еı�������
172 unsigned long get_free_page(void)
173 {
174 register unsigned long __res asm("ax");
175
// �������ڴ�ӳ���ֽ�λͼ�в���ֵΪ0���ֽ��Ȼ��Ѷ�Ӧ�����ڴ�ҳ�����㡣����õ�
// ��ҳ���ַ����ʵ�������ڴ�����������Ѱ�ҡ����û���ҵ�����ҳ����ȥ����ִ�н�����
// ���������²��ҡ���ؿ�������ҳ���ַ��
176 repeat:
177 __asm__("std ; repne ; scasb\n\t" // �÷���λ��al(0)���Ӧÿ��ҳ���(di)���ݱȽϣ�
178 "jne 1f\n\t" // ���û�е���0���ֽڣ�����ת����������0����
179 "movb $1,1(%%edi)\n\t" // 1 =>[1+edi], ����Ӧҳ���ڴ�ӳ�����λ��1��
180 "sall $12,%%ecx\n\t" // ҳ����*4K = ���ҳ����ʼ��ַ��
181 "addl %2,%%ecx\n\t" // �ټ��ϵͶ��ڴ��ַ����ҳ��ʵ��������ʼ��ַ��
182 "movl %%ecx,%%edx\n\t" // ��ҳ��ʵ����ʼ��ַ��edx�Ĵ�����
183 "movl $1024,%%ecx\n\t" // �Ĵ���ecx�ü���ֵ1024��
184 "leal 4092(%%edx),%%edi\n\t" // ��4092+edx��λ����edi����ҳ���ĩ�ˣ���
185 "rep ; stosl\n\t" // ��edi��ָ�ڴ����㣨����������ҳ�����㣩��
186 "movl %%edx,%%eax\n" // ��ҳ����ʼ��ַ��eax������ֵ����
187 "1:"
188 :"=a" (__res)
189 :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
190 "D" (mem_map+PAGING_PAGES-1)
191 :"di","cx","dx");
192 if (__res >= HIGH_MEMORY) // ҳ���ַ����ʵ���ڴ�����������Ѱ�ҡ�
193 goto repeat;
194 if (!__res && swap_out()) // ��û�õ�����ҳ����ִ�н��������������²��ҡ�
195 goto repeat;
196 return __res; // ���ؿ�������ҳ���ַ��
197 }
198
// �ڴ潻����ʼ����
199 void init_swapping(void)
200 {
// blk_size[]ָ��ָ�����豸�ŵĿ��豸�������顣�ÿ�������ÿһ���Ӧһ�����豸����
// ӵ�е����ݿ�������1���С=1KB����
201 extern int *blk_size[]; // blk_drv/ll_rw_blk.c��49��
202 int swap_size,i,j;
203
// ���û�ж��彻���豸�ء���������豸û�����ÿ������飬����ʾ��Ϣ�����ء�
204 if (!SWAP_DEV)
205 return;
206 if (!blk_size[MAJOR(SWAP_DEV)]) {
207 printk("Unable to get size of swap device\n\r");
208 return;
209 }
// ȡָ�������豸�ŵĽ��������ݿ�����swap_size����Ϊ0�أ����ܿ���С��100��
// ����ʾ��Ϣ�������豸��̫С����Ȼ���˳���
210 swap_size = blk_size[MAJOR(SWAP_DEV)][MINOR(SWAP_DEV)];
211 if (!swap_size)
212 return;
213 if (swap_size < 100) {
214 printk("Swap device too small (%d blocks)\n\r",swap_size);
215 return;
216 }
// �������ݿ�����ת���ɶ�Ӧ�ɽ���ҳ����������ֵ���ܴ���SWAP_BITS���ܱ�ʾ��ҳ������
// ������ҳ���������ô��� 32768�� Ȼ������һҳ�����ڴ�������Ž���ҳ��λӳ������
// swap_bitmap������ÿ1���ش���1ҳ����ҳ�档
217 swap_size >>= 2;
218 if (swap_size > SWAP_BITS)
219 swap_size = SWAP_BITS;
220 swap_bitmap = (char *) get_free_page();
221 if (!swap_bitmap) {
222 printk("Unable to start swapping: out of memory :-)\n\r");
223 return;
224 }
// read_swap_page(nr, buffer)������Ϊll_rw_page(READ,SWAP_DEV,(nr),(buffer))��
// �μ�linux/mm.h�ļ���11�С�����ѽ����豸�ϵ�ҳ��0����swap_bitmapҳ���С�
// ��ҳ���ǽ���������ҳ�档���е�4086�ֽڿ�ʼ������10���ַ��Ľ����豸������
// ������SWAP-SPACE������û���ҵ��������ַ�������˵������һ����Ч�Ľ����豸��
// ������ʾ��Ϣ���ͷŸ����������ҳ�沢�˳����������������ַ����ֽ����㡣
225 read_swap_page(0,swap_bitmap);
226 if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {
227 printk("Unable to find swap-space signature\n\r");
228 free_page((long) swap_bitmap);
229 swap_bitmap = NULL;
230 return;
231 }
232 memset(swap_bitmap+4086,0,10);
// Ȼ�������Ľ���λӳ��ͼ��Ӧ��32768������λȫΪ0����λͼ������λ�ı���λ0��
// ���ʾλͼ�����⣬������ʾ������Ϣ���ͷ�λͼռ�õ�ҳ�沢�˳�������Ϊ�˼ӿ���
// �ٶȣ��������Ƚ���ѡ�鿴λͼ��λ0�����һ������ҳ���Ӧ�ı���λ����swap_size
// ����ҳ���Ӧ�ı���λ���Լ����SWAP_BITS��32768������λ��
233 for (i = 0 ; i < SWAP_BITS ; i++) {
234 if (i == 1)
235 i = swap_size;
236 if (bit(swap_bitmap,i)) {
237 printk("Bad swap-space bit-map\n\r");
238 free_page((long) swap_bitmap);
239 swap_bitmap = NULL;
240 return;
241 }
242 }
// Ȼ������ϸ�ؼ��λ1��λswap_size���б���λ�Ƿ�Ϊ0�����в���0�ı���λ���ڣ�
// ���ʾλͼ�����⣬�����ͷ�λͼռ�õ�ҳ�沢�˳�������������ʾ�����豸��������
// �Լ�����ҳ�����ͽ����ռ����ֽ�����
243 j = 0;
244 for (i = 1 ; i < swap_size ; i++)
245 if (bit(swap_bitmap,i))
246 j++;
247 if (!j) {
248 free_page((long) swap_bitmap);
249 swap_bitmap = NULL;
250 return;
251 }
252 printk("Swap device ok: %d pages (%d bytes) swap-space\n\r",j,j*4096);
253 }
254
1 #ifndef _A_OUT_H
2 #define _A_OUT_H
3
4 #define __GNU_EXEC_MACROS__
5
// ��6--108���Ǹ��ļ���1���֡�����Ŀ���ļ�ִ�нṹ�Լ���ز����ĺ궨�塣
// Ŀ���ļ�ͷ�ṹ���μ���������ϸ˵����
// =============================
// unsigned long a_magic // ִ���ļ�ħ����ʹ��N_MAGIC�Ⱥ���ʡ�
// unsigned a_text // ���볤�ȣ��ֽ�����
// unsigned a_data // ���ݳ��ȣ��ֽ�����
// unsigned a_bss // �ļ��е�δ��ʼ�����������ȣ��ֽ�����
// unsigned a_syms // �ļ��еķ��ű����ȣ��ֽ�����
// unsigned a_entry // ִ�п�ʼ��ַ��
// unsigned a_trsize // �����ض�λ��Ϣ���ȣ��ֽ�����
// unsigned a_drsize // �����ض�λ��Ϣ���ȣ��ֽ�����
// -----------------------------
6 struct exec {
7 unsigned long a_magic; /* Use macros N_MAGIC, etc for access */
8 unsigned a_text; /* length of text, in bytes */
9 unsigned a_data; /* length of data, in bytes */
10 unsigned a_bss; /* length of uninitialized data area for file, in bytes */
11 unsigned a_syms; /* length of symbol table data in file, in bytes */
12 unsigned a_entry; /* start address */
13 unsigned a_trsize; /* length of relocation info for text, in bytes */
14 unsigned a_drsize; /* length of relocation info for data, in bytes */
15 };
16
// ����ȡ����exec�ṹ�е�ħ����
17 #ifndef N_MAGIC
18 #define N_MAGIC(exec) ((exec).a_magic)
19 #endif
20
21 #ifndef OMAGIC
22 /* Code indicating object file or impure executable. */
/* ָ��ΪĿ���ļ����߲����Ŀ�ִ���ļ��Ĵ��� */
// ��ʷ��������PDP-11������ϣ�ħ�����������ǰ˽�����0407��0x107������λ��ִ�г���
// ͷ�ṹ�Ŀ�ʼ����ԭ����PDP-11��һ����תָ���ʾ��ת�����7���ֺ�Ĵ��뿪ʼ����
// �������س���loader���Ϳ����ڰ�ִ���ļ������ڴ��ֱ����ת��ָ�ʼ�����С� ����
// ��û�г���ʹ�����ַ�����������˽�����ȴ��Ϊʶ���ļ����͵ı�־��ħ����������������
// OMAGIC������Ϊ��Old Magic ����˼��
23 #define OMAGIC 0407
24 /* Code indicating pure executable. */
/* ָ��Ϊ����ִ���ļ��Ĵ��� */ // New Magic��1975���Ժ�ʼʹ�á��漰�����ơ�
25 #define NMAGIC 0410 // 0410 == 0x108
26 /* Code indicating demand-paged executable. */
/* ָ��Ϊ�����ҳ�����Ŀ�ִ���ļ� */ // ��ͷ�ṹռ���ļ���ʼ��1K�ռ䡣
27 #define ZMAGIC 0413 // 0413 == 0x10b
28 #endif /* not OMAGIC */
29 // �����һ��QMAGIC����Ϊ�˽�Լ����������������ִ���ļ���ͷ�ṹ�������մ�š�
// ����������ж�ħ���ֶε���ȷ�ԡ����ħ�����ܱ�ʶ�����档
30 #ifndef N_BADMAG
31 #define N_BADMAG(x) \
32 (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
33 && N_MAGIC(x) != ZMAGIC)
34 #endif
35
36 #define _N_BADMAG(x) \
37 (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC \
38 && N_MAGIC(x) != ZMAGIC)
39
// Ŀ���ļ�ͷ�ṹĩ�˵�1024�ֽ�֮��ij��ȡ�
40 #define _N_HDROFF(x) (SEGMENT_SIZE - sizeof (struct exec))
41
// ��������ڲ���Ŀ���ļ������ݣ�����.oģ���ļ��Ϳ�ִ���ļ���
// ���벿����ʼƫ��ֵ��
// ����ļ��� ZMAGIC���͵ģ�����ִ���ļ�����ô���벿���Ǵ�ִ���ļ���1024�ֽ�ƫ�ƴ�
// ��ʼ������ִ�д��벿�ֽ���ִ��ͷ�ṹĩ�ˣ�32�ֽڣ���ʼ�����ļ���ģ���ļ���OMAGIC
// ���ͣ���
42 #ifndef N_TXTOFF
43 #define N_TXTOFF(x) \
44 (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
45 #endif
46
// ���ݲ�����ʼƫ��ֵ���Ӵ��벿��ĩ�˿�ʼ��
47 #ifndef N_DATOFF
48 #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
49 #endif
50
// �����ض�λ��Ϣƫ��ֵ�������ݲ���ĩ�˿�ʼ��
51 #ifndef N_TRELOFF
52 #define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
53 #endif
54
// �����ض�λ��Ϣƫ��ֵ���Ӵ����ض�λ��Ϣĩ�˿�ʼ��
55 #ifndef N_DRELOFF
56 #define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
57 #endif
58
// ���ű�ƫ��ֵ�����������ݶ��ض�λ��ĩ�˿�ʼ��
59 #ifndef N_SYMOFF
60 #define N_SYMOFF(x) (N_DRELOFF(x) + (x).a_drsize)
61 #endif
62
// �ַ�����Ϣƫ��ֵ���ڷ��ű�֮��
63 #ifndef N_STROFF
64 #define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
65 #endif
66
// ����Կ�ִ���ļ������ص��ڴ棨���ռ䣩�е�λ��������в�����
67 /* Address of text segment in memory after it is loaded. */
/* ����μ��غ����ڴ��еĵ�ַ */
68 #ifndef N_TXTADDR
69 #define N_TXTADDR(x) 0 // �ɼ�������δӵ�ַ0��ʼִ�С�
70 #endif
71
72 /* Address of data segment in memory after it is loaded.
73 Note that it is up to you to define SEGMENT_SIZE
74 on machines not listed here. */
/* ���ݶμ��غ����ڴ��еĵ�ַ��
ע�⣬��������û���г����ƵĻ�������Ҫ���Լ�������
��Ӧ��SEGMENT_SIZE */
75 #if defined(vax) || defined(hp300) || defined(pyr)
76 #define SEGMENT_SIZE PAGE_SIZE
77 #endif
78 #ifdef hp300
79 #define PAGE_SIZE 4096
80 #endif
81 #ifdef sony
82 #define SEGMENT_SIZE 0x2000
83 #endif /* Sony. */
84 #ifdef is68k
85 #define SEGMENT_SIZE 0x20000
86 #endif
87 #if defined(m68k) && defined(PORTAR)
88 #define PAGE_SIZE 0x400
89 #define SEGMENT_SIZE PAGE_SIZE
90 #endif
91
// ���Linux 0.12�ں˰��ڴ�ҳ����Ϊ4KB���δ�С����Ϊ1KB�����û��ʹ������Ķ��塣
92 #define PAGE_SIZE 4096
93 #define SEGMENT_SIZE 1024
94
// �Զ�Ϊ��Ĵ�С����λ��ʽ����
95 #define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
96
// �����β��ַ��
97 #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
98
// ���ݶο�ʼ��ַ��
// ����ļ���OMAGIC���͵ģ���ô���ݶξ�ֱ�ӽ������κ��档����Ļ����ݶε�ַ�Ӵ���
// �κ���α߽翪ʼ��1KB�߽���룩������ZMAGIC���͵��ļ���
99 #ifndef N_DATADDR
100 #define N_DATADDR(x) \
101 (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
102 : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
103 #endif
104
105 /* Address of bss segment in memory after it is loaded. */
/* bss�μ��ص��ڴ��Ժ�ĵ�ַ */
// δ��ʼ�����ݶ�bbsλ�����ݶκ��棬�������ݶΡ�
106 #ifndef N_BSSADDR
107 #define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
108 #endif
109
// ��110��185���ǵ�2���֡���Ŀ���ļ��еķ��ű������ز�������ж����˵����
// a.outĿ���ļ��з��ű���ṹ�����ű���¼�ṹ�����μ���������ϸ˵����
110 #ifndef N_NLIST_DECLARED
111 struct nlist {
112 union {
113 char *n_name;
114 struct nlist *n_next;
115 long n_strx;
116 } n_un;
117 unsigned char n_type; // ���ֽڷֳ�3���ֶΣ�146--154������Ӧ�ֶε������롣
118 char n_other;
119 short n_desc;
120 unsigned long n_value;
121 };
122 #endif
123
// ���涨��nlist�ṹ��n_type�ֶ�ֵ�ij������š�
124 #ifndef N_UNDF
125 #define N_UNDF 0
126 #endif
127 #ifndef N_ABS
128 #define N_ABS 2
129 #endif
130 #ifndef N_TEXT
131 #define N_TEXT 4
132 #endif
133 #ifndef N_DATA
134 #define N_DATA 6
135 #endif
136 #ifndef N_BSS
137 #define N_BSS 8
138 #endif
139 #ifndef N_COMM
140 #define N_COMM 18
141 #endif
142 #ifndef N_FN
143 #define N_FN 15
144 #endif
145
// ����3������������nlist�ṹ��n_type�ֶε������루�˽��̱�ʾ����
146 #ifndef N_EXT
147 #define N_EXT 1 // 0x01��0b0000,0001�������Ƿ����ⲿ�ģ�ȫ�ֵģ���
148 #endif
149 #ifndef N_TYPE
150 #define N_TYPE 036 // 0x1e��0b0001,1110�����ŵ�����λ��
151 #endif
152 #ifndef N_STAB // STAB -- ���ű����ͣ�Symbol table types����
153 #define N_STAB 0340 // 0xe0��0b1110,0000���⼸���������ڷ��ŵ�������
154 #endif
155
156 /* The following type indicates the definition of a symbol as being
157 an indirect reference to another symbol. The other symbol
158 appears as an undefined reference, immediately following this symbol.
159
160 Indirection is asymmetrical. The other symbol's value will be used
161 to satisfy requests for the indirect symbol, but not vice versa.
162 If the other symbol does not have a definition, libraries will
163 be searched to find a definition. */
/* ���������ָ����һ�����ŵĶ�������Ϊ����һ�����ŵļ�����á����Ӹ�
* ���ŵ������ķ��ų���Ϊδ��������á�
*
* ���ּ�������Dz��ԳƵġ���һ�����ŵ�ֵ�������������ӷ��ŵ�Ҫ��
* ����֮��Ȼ�������һ������û�ж��壬����������Ѱ��һ������ */
164 #define N_INDR 0xa
165
166 /* The following symbols refer to set elements.
167 All the N_SET[ATDB] symbols with the same name form one set.
168 Space is allocated for the set in the text section, and each set
169 element's value is stored into one word of the space.
170 The first word of the space is the length of the set (number of elements).
171
172 The address of the set is made into an N_SETV symbol
173 whose name is the same as the name of the set.
174 This symbol acts like a N_DATA global symbol
175 in that it can satisfy undefined external references. */
/* ����ķ����뼯��Ԫ���йء����о�����ͬ����N_SET[ATDB]�ķ���
�γ�һ�����ϡ��ڴ��벿������Ϊ���Ϸ����˿ռ䣬����ÿ������Ԫ��
��ֵ�����һ���֣�word���Ŀռ��С��ռ�ĵ�һ���ִ��м��ϵij��ȣ�����Ԫ����Ŀ����
���ϵĵ�ַ������һ��N_SETV�����У����������뼯��ͬ����
������δ������ⲿ���÷��棬�÷��ŵ���Ϊ��һ��N_DATAȫ�ַ��š�*/
176
177 /* These appear as input to LD, in a .o file. */
/* ������Щ������ .o �ļ�������Ϊ���ӳ���LD�����롣*/
178 #define N_SETA 0x14 /* Absolute set element symbol */ /* ���Լ���Ԫ�ط��� */
179 #define N_SETT 0x16 /* Text set element symbol */ /* ���뼯��Ԫ�ط��� */
180 #define N_SETD 0x18 /* Data set element symbol */ /* ���ݼ���Ԫ�ط��� */
181 #define N_SETB 0x1A /* Bss set element symbol */ /* Bss����Ԫ�ط��� */
182
183 /* This is output from LD. */
/* ������LD�������*/
184 #define N_SETV 0x1C /* Pointer to set vector in data area. */
/* ָ���������м���������*/
185
186 #ifndef N_RELOCATION_INFO_DECLARED
187
188 /* This structure describes a single relocation to be performed.
189 The text-relocation section of the file is a vector of these structures,
190 all of which apply to the text section.
191 Likewise, the data-relocation section applies to the data section. */
/* ����ṹ���������ض�λ������ִ�С�
�ļ��Ĵ����ض�λ��������Щ�ṹ��һ�����飬������Щ�����ڴ��벿�֡�
���Ƶأ������ض�λ�����������ݲ��֡�*/
192
// a.outĿ���ļ��д���������ض�λ��Ϣ�ṹ��
193 struct relocation_info
194 {
195 /* Address (within segment) to be relocated. */
/* ������Ҫ�ض�λ�ĵ�ַ��*/
196 int r_address;
197 /* The meaning of r_symbolnum depends on r_extern. */
/* r_symbolnum�ĺ�����r_extern�йء�*/
198 unsigned int r_symbolnum:24;
199 /* Nonzero means value is a pc-relative offset
200 and it should be relocated for changes in its own address
201 as well as for changes in the symbol or section specified. */
/* ������ζ��ֵ��һ��pc��ص�ƫ��ֵ����������Լ���ַ�ռ�
�Լ����Ż�ָ���Ľڸı�ʱ����Ҫ���ض�λ */
202 unsigned int r_pcrel:1;
203 /* Length (as exponent of 2) of the field to be relocated.
204 Thus, a value of 2 indicates 1<<2 bytes. */
/* ��Ҫ���ض�λ���ֶγ��ȣ���2�Ĵη�����
��ˣ���ֵ��2���ʾ1<<2�ֽ�����*/
205 unsigned int r_length:2;
206 /* 1 => relocate with value of symbol.
207 r_symbolnum is the index of the symbol
208 in file's the symbol table.
209 0 => relocate with the address of a segment.
210 r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
211 (the N_EXT bit may be set also, but signifies nothing). */
/* 1 => �Է��ŵ�ֵ�ض�λ��
r_symbolnum���ļ����ű��з��ŵ�������
0 => �Զεĵ�ַ�����ض�λ��
r_symbolnum��N_TEXT��N_DATA��N_BSS��N_ABS
(N_EXT����λҲ���Ա����ã����Ǻ�������)��*/
212 unsigned int r_extern:1;
213 /* Four bits that aren't used, but when writing an object file
214 it is desirable to clear them. */
/* û��ʹ�õ�4������λ�����ǵ�����дһ��Ŀ���ļ�ʱ
��ý����Ǹ�λ����*/
215 unsigned int r_pad:4;
216 };
217 #endif /* no N_RELOCATION_INFO_DECLARED. */
218
219
220 #endif /* __A_OUT_GNU_H__ */
221
1 #ifndef _CONST_H
2 #define _CONST_H
3
4 #define BUFFER_END 0x200000 // ���建��ʹ���ڴ��ĩ�ˣ�������û��ʹ�øó�������
5
// i�ڵ����ݽṹ��i_mode�ֶεĸ���־λ��
6 #define I_TYPE 0170000 // ָ��i�ڵ����ͣ����������룩��
7 #define I_DIRECTORY 0040000 // ��Ŀ¼�ļ���
8 #define I_REGULAR 0100000 // �dz����ļ�������Ŀ¼�ļ��������ļ���
9 #define I_BLOCK_SPECIAL 0060000 // �ǿ��豸�����ļ���
10 #define I_CHAR_SPECIAL 0020000 // ���ַ��豸�����ļ���
11 #define I_NAMED_PIPE 0010000 // �������ܵ��ڵ㡣
12 #define I_SET_UID_BIT 0004000 // ��ִ��ʱ������Ч�û�ID���͡�
13 #define I_SET_GID_BIT 0002000 // ��ִ��ʱ������Ч��ID���͡�
14
15 #endif
16
1 #ifndef _CTYPE_H
2 #define _CTYPE_H
3
4 #define _U 0x01 /* upper */ // �ñ���λ���ڴ�д�ַ�[A-Z]��
5 #define _L 0x02 /* lower */ // �ñ���λ����Сд�ַ�[a-z]��
6 #define _D 0x04 /* digit */ // �ñ���λ��������[0-9]��
7 #define _C 0x08 /* cntrl */ // �ñ���λ���ڿ����ַ���
8 #define _P 0x10 /* punct */ // �ñ���λ���ڱ���ַ���
9 #define _S 0x20 /* white space (space/lf/tab) */ // �հ��ַ�����ո�\t��\n�ȡ�
10 #define _X 0x40 /* hex digit */ // �ñ���λ����ʮ���������֡�
11 #define _SP 0x80 /* hard space (0x20) */ // �ñ���λ���ڿո��ַ���0x20����
12
13 extern unsigned char _ctype[]; // �ַ��������飨��������������ַ���Ӧ��������ԡ�
14 extern char _ctmp; // һ����ʱ�ַ��������ڶ���lib/ctype.c�У���
15
// ������һЩȷ���ַ����͵ĺꡣ
16 #define isalnum(c) ((_ctype+1)[c]&(_U|_L|_D)) // ���ַ�������[A-Z]��[a-z]��[0-9]��
17 #define isalpha(c) ((_ctype+1)[c]&(_U|_L)) // ���ַ���
18 #define iscntrl(c) ((_ctype+1)[c]&(_C)) // �ǿ����ַ���
19 #define isdigit(c) ((_ctype+1)[c]&(_D)) // �����֡�
20 #define isgraph(c) ((_ctype+1)[c]&(_P|_U|_L|_D)) // ��ͼ���ַ���
21 #define islower(c) ((_ctype+1)[c]&(_L)) // ��Сд�ַ���
22 #define isprint(c) ((_ctype+1)[c]&(_P|_U|_L|_D|_SP)) // �ǿɴ�ӡ�ַ���
23 #define ispunct(c) ((_ctype+1)[c]&(_P)) // �DZ����š�
24 #define isspace(c) ((_ctype+1)[c]&(_S)) // �ǿհ��ַ���ո�,\f,\n,\r,\t,\v��
25 #define isupper(c) ((_ctype+1)[c]&(_U)) // �Ǵ�д�ַ���
26 #define isxdigit(c) ((_ctype+1)[c]&(_D|_X)) // ��ʮ���������֡�
27
// ���������������У������ǰʹ����ǰ��unsigned�������c Ӧ�ü����ţ�����ʾ�� (c)��
// ��Ϊ�ڳ�����c������һ�����ӵı���ʽ�����磬���������a + b�����������ţ����ں궨
// ���б���ˣ�(unsigned) a + b������Ȼ���ԡ��������ž�����ȷ��ʾ��(unsigned)(a + b)��
28 #define isascii(c) (((unsigned) c)<=0x7f) // ��ASCII�ַ���
29 #define toascii(c) (((unsigned) c)&0x7f) // ת����ASCII�ַ���
30
// ���������궨����ʹ��һ����ʱ����_ctmp��ԭ���ǣ��ں궨���У���IJ���ֻ�ܱ�ʹ��һ�Ρ�
// �����ڶ��߳���˵���Dz���ȫ�ģ���Ϊ���������߳̿�����ͬһʱ��ʹ�����������ʱ������
// ��˴�Linux 2.2.x�汾��ʼ����Ϊʹ������������ȡ���������궨�塣
31 #define tolower(c) (_ctmp=c,isupper(_ctmp)?_ctmp-('A'-'a'):_ctmp) // ת����Сд�ַ���
32 #define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) // ת���ɴ�д�ַ���
33
34 #endif
35
1 #ifndef _ERRNO_H
2 #define _ERRNO_H
3
4 /*
5 * ok, as I hadn't got any other source of information about
6 * possible error numbers, I was forced to use the same numbers
7 * as minix.
8 * Hopefully these are posix or something. I wouldn't know (and posix
9 * isn't telling me - they want $$$ for their f***ing standard).
10 *
11 * We don't use the _SIGN cludge of minix, so kernel returns must
12 * see to the sign by themselves.
13 *
14 * NOTE! Remember to change strerror() if you change this file!
15 */
/*
* ok��������û�еõ��κ������йس����ŵ����ϣ���ֻ��ʹ����minixϵͳ
* ��ͬ�ij������ˡ�
* ϣ����Щ��POSIX���ݵĻ�����һ���̶����������ģ��Ҳ�֪��������POSIX
* û�и����� - Ҫ������ǵĻ쵰����Ҫ��Ǯ����
*
* ����û��ʹ��minix������_SIGN�أ������ں˵ķ���ֵ�����Լ���������š�
*
* ע�⣡�����ı���ļ��Ļ�������ҲҪ��strerror()������
*/
16
// ϵͳ�����Լ��ܶ�⺯������һ�������ֵ�Ա�ʾ����ʧ�ܻ���������ֵͨ��ѡ��-1����
// ����һЩ�ض���ֵ����ʾ�������������ֵ��˵���������ˡ� �����Ҫ֪�����������ͣ�
// ����Ҫ�鿴��ʾϵͳ�����ŵı���errno���ñ������� errno.h �ļ����������ڳ���ʼִ
// ��ʱ�ñ���ֵ����ʼ��Ϊ0��
17 extern int errno;
18
// �ڳ���ʱ��ϵͳ���û�ѳ����ŷ��ڱ���errno�У���ֵ����Ȼ��-1����˳�������Ҫ֪
// ���������ţ�����Ҫ�鿴errno��ֵ��
19 #define ERROR 99 // һ�����
20 #define EPERM 1 // ����û�����ɡ�
21 #define ENOENT 2 // �ļ���Ŀ¼�����ڡ�
22 #define ESRCH 3 // ָ���Ľ��̲����ڡ�
23 #define EINTR 4 // �жϵ�ϵͳ���á�
24 #define EIO 5 // ����/�������
25 #define ENXIO 6 // ָ���豸���ַ�����ڡ�
26 #define E2BIG 7 // �����б�̫����
27 #define ENOEXEC 8 // ִ�г����ʽ����
28 #define EBADF 9 // ����(������)����
29 #define ECHILD 10 // �ӽ��̲����ڡ�
30 #define EAGAIN 11 // ��Դ��ʱ�����á�
31 #define ENOMEM 12 // �ڴ治�㡣
32 #define EACCES 13 // û������Ȩ�ޡ�
33 #define EFAULT 14 // ��ַ����
34 #define ENOTBLK 15 // ���ǿ��豸�ļ���
35 #define EBUSY 16 // ��Դ��æ��
36 #define EEXIST 17 // �ļ��Ѵ��ڡ�
37 #define EXDEV 18 // �Ƿ����ӡ�
38 #define ENODEV 19 // �豸�����ڡ�
39 #define ENOTDIR 20 // ����Ŀ¼�ļ���
40 #define EISDIR 21 // ��Ŀ¼�ļ���
41 #define EINVAL 22 // ��������
42 #define ENFILE 23 // ϵͳ���ļ���̫�ࡣ
43 #define EMFILE 24 // ���ļ���̫�ࡣ
44 #define ENOTTY 25 // ��ǡ����IO���Ʋ���(û��tty�ն�)��
45 #define ETXTBSY 26 // ����ʹ�á�
46 #define EFBIG 27 // �ļ�̫��
47 #define ENOSPC 28 // �豸�������豸�Ѿ�û�пռ䣩��
48 #define ESPIPE 29 // ��Ч���ļ�ָ���ض�λ��
49 #define EROFS 30 // �ļ�ϵͳֻ����
50 #define EMLINK 31 // ����̫�ࡣ
51 #define EPIPE 32 // �ܵ�����
52 #define EDOM 33 // ��(domain)������
53 #define ERANGE 34 // ���̫��
54 #define EDEADLK 35 // ������Դ������
55 #define ENAMETOOLONG 36 // �ļ���̫����
56 #define ENOLCK 37 // û���������á�
57 #define ENOSYS 38 // ���ܻ�û��ʵ�֡�
58 #define ENOTEMPTY 39 // Ŀ¼���ա�
59
60 /* Should never be seen by user programs */
/* �û�����Ӧ�ü������������д���� */
61 #define ERESTARTSYS 512 // ����ִ��ϵͳ���á�
62 #define ERESTARTNOINTR 513 // ����ִ��ϵͳ���ã����жϡ�
63
64 #endif
65
1 #ifndef _FCNTL_H
2 #define _FCNTL_H
3
4 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
5
6 /* open/fcntl - NOCTTY, NDELAY isn't implemented yet */
/* open/fcntl - NOCTTY��NDELAY���ڻ�û��ʵ�� */
7 #define O_ACCMODE 00003 // �ļ�����ģʽ�����롣
// ���ļ�open()���ļ����ƺ���fcntl()ʹ�õ��ļ�����ģʽ��ͬʱֻ��ʹ������֮һ��
8 #define O_RDONLY 00 // ��ֻ����ʽ���ļ���
9 #define O_WRONLY 01 // ��ֻд��ʽ���ļ���
10 #define O_RDWR 02 // �Զ�д��ʽ���ļ���
// �������ļ������Ͳ�����־������open()�������������ģʽ��'λ��'�ķ�ʽһ��ʹ�á�
11 #define O_CREAT 00100 /* not fcntl */ // ����ļ������ھʹ�����fcntl�������á�
12 #define O_EXCL 00200 /* not fcntl */ // ��ռʹ���ļ���־��
13 #define O_NOCTTY 00400 /* not fcntl */ // ����������նˡ�
14 #define O_TRUNC 01000 /* not fcntl */ // ���ļ��Ѵ�������д�������Ƚ�Ϊ0��
15 #define O_APPEND 02000 // �����ӷ�ʽ���ļ�ָ����Ϊ�ļ�β��
16 #define O_NONBLOCK 04000 /* not fcntl */ // ��������ʽ�Ͳ����ļ���
17 #define O_NDELAY O_NONBLOCK // ��������ʽ�Ͳ����ļ���
18
19 /* Defines for fcntl-commands. Note that currently
20 * locking isn't supported, and other things aren't really
21 * tested.
22 */
/* ���涨����fcntl�����ע��Ŀǰ�������û��֧�֣�������
* ����ʵ���ϻ�û�в��Թ���
*/
// ����(������)��������fcntl()�����cmd����
23 #define F_DUPFD 0 /* dup */ // �����ļ����Ϊ��С��ֵ�ľ����
24 #define F_GETFD 1 /* get f_flags */ // ȡ�����־����1����־FD_CLOEXEC��
25 #define F_SETFD 2 /* set f_flags */ // �����ļ������־��
26 #define F_GETFL 3 /* more flags (cloexec) */ // ȡ�ļ�״̬��־�ͷ���ģʽ��
27 #define F_SETFL 4 // �����ļ�״̬��־�ͷ���ģʽ��
// �������ļ��������fcntl()�ĵ���������lock��ָ��flock�ṹ��ָ�롣
28 #define F_GETLK 5 /* not implemented */ // ������ֹ������flock�ṹ��
29 #define F_SETLK 6 // ����(F_RDLCK��F_WRLCK)�����(F_UNLCK)������
30 #define F_SETLKW 7 // �ȴ����û����������
31
32 /* for F_[GET|SET]FL */
/* ���� F_GETFL��F_SETFL */
// ��ִ��exec()�غ���ʱ��Ҫ�رյ��ļ������(ִ��ʱ�ر� - Close On EXECution)
33 #define FD_CLOEXEC 1 /* actually anything with low bit set goes */
/* ʵ����ֻҪ��λΪ1���� */
34
35 /* Ok, these are locking features, and aren't implemented at any
36 * level. POSIX wants them.
37 */
/* OK���������������ͣ��κκ����ж���û��ʵ�֡�POSIX��Ҫ����Щ���͡�
*/
38 #define F_RDLCK 0 // ��������������
39 #define F_WRLCK 1 // ��ռ��д�ļ�������
40 #define F_UNLCK 2 // �������
41
42 /* Once again - not implemented, but ... */
/* ͬ�� - Ҳ��û��ʵ�֣�����... */
// �ļ������������ݽṹ����������Ӱ���ļ��ε�����(l_type)����ʼƫ��(l_whence)��
// ���ƫ��(l_start)����������(l_len)��ʵʩ�����Ľ���id��
43 struct flock {
44 short l_type; // �������ͣ�F_RDLCK��F_WRLCK��F_UNLCK����
45 short l_whence; // ��ʼƫ��(SEEK_SET��SEEK_CUR��SEEK_END)��
46 off_t l_start; // ���������Ŀ�ʼ�������ƫ�ƣ��ֽ�������
47 off_t l_len; // ���������Ĵ�С�������0��Ϊ���ļ�ĩβ��
48 pid_t l_pid; // �����Ľ���id��
49 };
50
// ������ʹ��������־������ĺ���ԭ�͡�
// �������ļ�����дһ���Ѵ����ļ���
// ����filename���������ļ����ļ�����mode�Ǵ����ļ������ԣ���include/sys/stat.h����
51 extern int creat(const char * filename,mode_t mode);
// �ļ������������Ӱ���ļ��Ĵ�
// ����fildes���ļ������cmd�Dz������������23--30�С��ú����������¼�����ʽ��
// int fcntl(int fildes, int cmd);
// int fcntl(int fildes, int cmd, long arg);
// int fcntl(int fildes, int cmd, struct flock *lock);
52 extern int fcntl(int fildes,int cmd, ...);
// ���ļ������ļ����ļ����֮�佨����ϵ��
// ����filename�������ļ����ļ�����flags������7-17���ϵı�־����ϡ�
53 extern int open(const char * filename, int flags, ...);
54
55 #endif
56
1 #ifndef _SIGNAL_H
2 #define _SIGNAL_H
3
4 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
5
6 typedef int sig_atomic_t; // �����ź�ԭ�Ӳ������͡�
7 typedef unsigned int sigset_t; /* 32 bits */ // �����źż����͡�
8
9 #define _NSIG 32 // �����ź����� -- 32 �֡�
10 #define NSIG _NSIG // NSIG = _NSIG
11
// ������Щ��Linux 0.12�ں��ж�����źš����а�����POSIX.1Ҫ�������20���źš�
12 #define SIGHUP 1 // Hang Up -- �ҶϿ����ն˻���̡�
13 #define SIGINT 2 // Interrupt -- ���Լ��̵��жϡ�
14 #define SIGQUIT 3 // Quit -- ���Լ��̵��˳���
15 #define SIGILL 4 // Illeagle -- �Ƿ�ָ�
16 #define SIGTRAP 5 // Trap -- ���ٶϵ㡣
17 #define SIGABRT 6 // Abort -- �쳣������
18 #define SIGIOT 6 // IO Trap -- ͬ�ϡ�
19 #define SIGUNUSED 7 // Unused -- û��ʹ�á�
20 #define SIGFPE 8 // FPE -- ������������
21 #define SIGKILL 9 // Kill -- ǿ�Ƚ�����ֹ��
22 #define SIGUSR1 10 // User1 -- �û��ź�1�����̿�ʹ�á�
23 #define SIGSEGV 11 // Segment Violation -- ��Ч�ڴ����á�
24 #define SIGUSR2 12 // User2 -- �û��ź�2�����̿�ʹ�á�
25 #define SIGPIPE 13 // Pipe -- �ܵ�д���������ߡ�
26 #define SIGALRM 14 // Alarm -- ʵʱ��ʱ��������
27 #define SIGTERM 15 // Terminate -- ������ֹ��
28 #define SIGSTKFLT 16 // Stack Fault -- ջ������Э����������
29 #define SIGCHLD 17 // Child -- �ӽ���ֹͣ����ֹ��
30 #define SIGCONT 18 // Continue -- �ָ����̼���ִ�С�
31 #define SIGSTOP 19 // Stop -- ֹͣ���̵�ִ�С�
32 #define SIGTSTP 20 // TTY Stop -- tty����ֹͣ���̣��ɺ��ԡ�
33 #define SIGTTIN 21 // TTY In -- ��̨�����������롣
34 #define SIGTTOU 22 // TTY Out -- ��̨�������������
35
36 /* Ok, I haven't implemented sigactions, but trying to keep headers POSIX */
/* OK���һ�û��ʵ��sigactions�ı��ƣ�����ͷ�ļ�����ϣ������POSIX�� */
// ����ԭע���Ѿ���ʱ����Ϊ��0.12�ں����Ѿ�ʵ����sigaction()��������sigaction�ṹ
// sa_flags��־�ֶο�ȡ�ķ��ų���ֵ��
37 #define SA_NOCLDSTOP 1 // ���ӽ��̴���ֹͣ״̬���Ͳ���SIGCHLD������
38 #define SA_INTERRUPT 0x20000000 // ϵͳ���ñ��ź��жϺ���������ϵͳ���á�
39 #define SA_NOMASK 0x40000000 // ����ֹ��ָ�����źŴ������������յ����źš�
40 #define SA_ONESHOT 0x80000000 // �źž��һ�������ù��ͻָ���Ĭ�ϴ��������
41
// ���³�������sigprocmask(how, )-- �ı������źż�(������)�����ڸı�ú�������Ϊ��
42 #define SIG_BLOCK 0 /* for blocking signals */ // �������źż��м��ϸ����źš�
43 #define SIG_UNBLOCK 1 /* for unblocking signals */ // �������źż���ɾ��ָ���źš�
44 #define SIG_SETMASK 2 /* for setting the signal mask */ // ���������źż���
45
// ���������������Ŷ���ʾָ������ֵ�ĺ���ָ�룬�Ҷ���һ��int���Ͳ�����������ָ��
// ֵ�����Ͻ�ʵ���ϲ����ܳ��ֵĺ�����ֵַ������Ϊ����signal�����ĵڶ�����������
// �ڸ�֪�ںˣ����ں˴����źŻ���Զ��źŵĴ�����ʹ�÷����μ� kernel/signal.c����
// ��94--96��
46 #define SIG_DFL ((void (*)(int))0) /* default signal handling */
// Ĭ���źŴ��������źž������
47 #define SIG_IGN ((void (*)(int))1) /* ignore signal */
// �����źŵĴ�������
48 #define SIG_ERR ((void (*)(int))-1) /* error return from signal */
// �źŴ������ش���
49
// ���涨���ʼ��������sigaction�ṹ�ź�������ĺꡣ
50 #ifdef notdef
51 #define sigemptyset(mask) ((*(mask) = 0), 1) // ��mask���㡣
52 #define sigfillset(mask) ((*(mask) = ~0), 1) // ��mask���б���λ��λ��
53 #endif
54
// ������sigaction�����ݽṹ��
// sa_handler�Ƕ�Ӧij�ź�ָ��Ҫ��ȡ���ж��������������SIG_DFL����SIG_IGN�����Ը�
// �źţ�Ҳ������ָ�������źź�����һ��ָ�롣
// sa_mask�����˶��źŵ������룬���źų���ִ��ʱ����������Щ�źŵĴ�����
// sa_flagsָ���ı��źŴ������̵��źż���������37-40�е�λ��־����ġ�
// sa_restorer�ǻָ�����ָ�룬�ɺ�����Libc�ṩ�����������û�̬��ջ���μ�signal.c��
// ���⣬�����źŴ������ź�Ҳ��������������ʹ����SA_NOMASK��־��
55 struct sigaction {
56 void (*sa_handler)(int);
57 sigset_t sa_mask;
58 int sa_flags;
59 void (*sa_restorer)(void);
60 };
61
// ����signal����������Ϊ�ź�_sig��װһ�µ��źŴ��������źž��������sigaction()
// ���ơ��ú�����������������ָ����Ҫ������ź�_sig������һ������������ֵ�ĺ���ָ��
// _func���ú�������ֵҲ�Ǿ���һ��int���������һ��(int)��������ֵ�ĺ���ָ�룬����
// �������źŵ�ԭ���������
62 void (*signal(int _sig, void (*_func)(int)))(int);
// �������������ڷ����źš�kill() �������κν��̻�����鷢���źš�raise()������ǰ��
// �����������źš������õȼ���kill(getpid(),sig)���μ�kernel/exit.c��60�С�
63 int raise(int sig);
64 int kill(pid_t pid, int sig);
// �ڽ��̵�����ṹ�У�����һ���Ա���λ��ʾ��ǰ���̴�������32λ�ź��ֶ�signal���⣬
// ����һ��ͬ���Ա���λ��ʾ���������ν��̵�ǰ�����źż��������źż������ֶ�blocked��
// Ҳ��32λ��ÿ�����ش���һ����Ӧ�������źš��Ľ��̵������źż�����������������
// ��ָ�����źš� ������������������ڲ������������źż�����Ȼ��ʵ�������ܼ���
// ���汾�ں��л�δʵ�֡�
// ����sigaddset() �� sigdelset() ���ڶ��źż��е��źŽ�������ɾ�ġ� sigaddset()��
// ����maskָ����źż�������ָ�����ź�signo��sigdelset��֮������sigemptyset()��
// sigfillset() ���ڳ�ʼ�����������źż��� ÿ��������ʹ���źż�ǰ������Ҫʹ����������
// ��֮һ�������źż����г�ʼ���� sigemptyset()����������ε������źţ�Ҳ����Ӧ���е�
// �źš�sigfillset()���źż������������źţ�Ҳ�����������źš���Ȼ SIGINT�� SIGSTOP
// �Dz��ܱ����εġ�
// sigismember()���ڲ���һ��ָ���ź��Ƿ����źż��У�1 - �ǣ�0 - ���ǣ�-1 - ��������
65 int sigaddset(sigset_t *mask, int signo);
66 int sigdelset(sigset_t *mask, int signo);
67 int sigemptyset(sigset_t *mask);
68 int sigfillset(sigset_t *mask);
69 int sigismember(sigset_t *mask, int signo); /* 1 - is, 0 - not, -1 error */
// ��set�е��źŽ��м�⣬���Ƿ��й�����źš���set�з��ؽ����е�ǰ���������źż���
70 int sigpending(sigset_t *set);
// ���溯�����ڸı����Ŀǰ���������źż����ź������룩����oldset����NULL����ͨ����
// ���ؽ��̵�ǰ�����źż�����setָ�벻��NULL�������how��41-43�У�ָʾ�Ľ�������
// �źż���
71 int sigprocmask(int how, sigset_t *set, sigset_t *oldset);
// ���溯���� sigmask ��ʱ�滻���̵��ź�������,Ȼ����ͣ�ý���ֱ���յ�һ���źš�����
// ��ijһ�źŲ��Ӹ��źŴ��������з��أ���ú���Ҳ���أ������ź��������ָ������õ���
// ǰ��ֵ��
72 int sigsuspend(sigset_t *sigmask);
// sigaction() �������ڸı�������յ�ָ���ź�ʱ����ȡ���ж������ı��źŵĴ�������ܡ�
// �μ���kernel/signal.c�����˵����
73 int sigaction(int sig, struct sigaction *act, struct sigaction *oldact);
74
75 #endif /* _SIGNAL_H */
76
1 #ifndef _STDARG_H
2 #define _STDARG_H
3
4 typedef char *va_list; // ����va_list��һ���ַ�ָ�����͡�
5
6 /* Amount of space required in an argument list for an arg of type TYPE.
7 TYPE may alternatively be an expression whose type is used. */
/* �������������ΪTYPE��arg�����б���Ҫ��Ŀռ�������
TYPEҲ������ʹ�ø����͵�һ������ʽ */
8
// ������䶨����ȡ�����TYPE���͵��ֽڳ���ֵ����int����(4)�ı�����
9 #define __va_rounded_size(TYPE) \
10 (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
11
// ����������ʼ��ָ��AP��ʹ��ָ�������Ŀɱ�������ĵ�һ��������
// �ڵ�һ�ε���va_arg��va_end֮ǰ���������ȵ���va_start�ꡣ����LASTARG�Ǻ�������
// �����ұ߲����ı�ʶ������'...'��ߵ�һ����ʶ����AP�ǿɱ����������ָ�룬LASTARG��
// ���һ��ָ��������&(LASTARG) ����ȡ���ַ������ָ�룩�����Ҹ�ָ�����ַ����͡�����
// LASTARG�Ŀ���ֵ��AP���ǿɱ�������е�һ��������ָ�롣�ú�û�з���ֵ��
// ��17���ϵĺ��� __builtin_saveregs() ����gcc�Ŀ����libgcc2.c�ж���ģ����ڱ���
// �Ĵ����� ���˵���μ� gcc�ֲᡰTarget Description Macros�����С�Implementing the
// Varargs Macros��С�ڡ�
12 #ifndef __sparc__
13 #define va_start(AP, LASTARG) \
14 (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
15 #else
16 #define va_start(AP, LASTARG) \
17 (__builtin_saveregs (), \
18 AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
19 #endif
20
// ����ú����ڱ����ú������һ���������ء�va_end������APʹ�������µ���
// va_start֮ǰ���ܱ�ʹ�á�va_end������va_arg�������еIJ������ٱ����á�
21 void va_end (va_list); /* Defined in gnulib */ /* ��gnulib��� */
22 #define va_end(AP)
23
// �����������չ����ʽʹ������һ�������ݲ���������ͬ�����ͺ�ֵ��
// ����ȱʡֵ��va_arg �������ַ��������ַ��������͡��ڵ�һ��ʹ�� va_argʱ������
// �ر��еĵ�һ��������������ÿ�ε��ö������ر��е���һ������������ͨ���ȷ���AP��Ȼ
// ��������ֵ��ָ����һ����ʵ�ֵġ�va_arg ʹ��TYPE ����ɷ��ʺͶ�λ��һ�ÿ����һ
// ��va_arg��������AP��ָʾ���е���һ������
24 #define va_arg(AP, TYPE) \
25 (AP += __va_rounded_size (TYPE), \
26 *((TYPE *) (AP - __va_rounded_size (TYPE))))
27
28 #endif /* _STDARG_H */
29
1 #ifndef _STDDEF_H
2 #define _STDDEF_H
3
4 #ifndef _PTRDIFF_T
5 #define _PTRDIFF_T
6 typedef long ptrdiff_t; // ����ָ�������������͡�
7 #endif
8
9 #ifndef _SIZE_T
10 #define _SIZE_T
11 typedef unsigned long size_t; // sizeof���ص����͡�
12 #endif
13
14 #undef NULL
15 #define NULL ((void *)0) // ��ָ�롣
16
// ���涨����һ������ij��Ա��������ƫ��λ�õĺꡣʹ�øú����ȷ��һ����Ա���ֶΣ���
// �������Ľṹ�����дӽṹ��ʼ��������ֽ�ƫ��������Ľ��������Ϊ size_t ��������
// ������ʽ��������һ�������÷���((TYPE *)0)�ǽ�һ������0����Ͷ�䣨type cast������
// �ݶ���ָ�����ͣ�Ȼ���ڸý���Ͻ������㡣
17 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
18
19 #endif
20
1 #ifndef _STRING_H_
2 #define _STRING_H_
3
4 #ifndef NULL
5 #define NULL ((void *) 0)
6 #endif
7
8 #ifndef _SIZE_T
9 #define _SIZE_T
10 typedef unsigned int size_t;
11 #endif
12
13 extern char * strerror(int errno);
14
15 /*
16 * This string-include defines all string functions as inline
17 * functions. Use gcc. It also assumes ds=es=data space, this should be
18 * normal. Most of the string-functions are rather heavily hand-optimized,
19 * see especially strtok,strstr,str[c]spn. They should work, but are not
20 * very easy to understand. Everything is done entirely within the register
21 * set, making the functions fast and clean. String instructions have been
22 * used through-out, making for "slightly" unclear code :-)
23 *
24 * (C) 1991 Linus Torvalds
25 */
/*
* ����ַ���ͷ�ļ�����Ƕ��������ʽ�����������ַ�������������ʹ��gccʱ��ͬʱ
* �ٶ���ds=es=���ݿռ䣬��Ӧ���dz���ġ���������ַ����������Ǿ��ֹ����д���
* �Ż��ģ������Ǻ���strtok��strstr��str[c]spn������Ӧ����������������ȴ������
* ô�������⡣���еIJ��������϶���ʹ�üĴ���������ɵģ���ʹ�ú������������ࡣ
* ���еط���ʹ�����ַ���ָ�����ʹ�ô��롰������������J
*
* (C) 1991 Linus Torvalds
*/
26
//// ��һ���ַ���(src)��������һ���ַ���(dest)��ֱ������NULL�ַ���ֹͣ��
// ������dest - Ŀ���ַ���ָ�룬src - Դ�ַ���ָ�롣
// %0 - esi(src)��%1 - edi(dest)��
27 extern inline char * strcpy(char * dest,const char *src)
28 {
29 __asm__("cld\n" // �巽��λ��
30 "1:\tlodsb\n\t" // ����DS:[esi]��1�ֽ���al��������esi��
31 "stosb\n\t" // �洢�ֽ�al��ES:[edi]��������edi��
32 "testb %%al,%%al\n\t" // �մ洢���ֽ���0��
33 "jne 1b" // �����������ת�����1�������������
34 ::"S" (src),"D" (dest):"si","di","ax");
35 return dest; // ����Ŀ���ַ���ָ�롣
36 }
37
//// ����Դ�ַ���count���ֽڵ�Ŀ���ַ�����
// ���Դ������С��count���ֽڣ����ӿ��ַ�(NULL)��Ŀ���ַ�����
// ������dest - Ŀ���ַ���ָ�룬src - Դ�ַ���ָ�룬count - �����ֽ�����
// %0 - esi(src)��%1 - edi(dest)��%2 - ecx(count)��
38 extern inline char * strncpy(char * dest,const char *src,int count)
39 {
40 __asm__("cld\n" // �巽��λ��
41 "1:\tdecl %2\n\t" // �Ĵ���ecx--��count--����
42 "js 2f\n\t" // ���count<0����ǰ��ת�����2��������
43 "lodsb\n\t" // ȡds:[esi]��1�ֽ���al������esi++��
44 "stosb\n\t" // �洢���ֽ���es:[edi]������edi++��
45 "testb %%al,%%al\n\t" // ���ֽ���0��
46 "jne 1b\n\t" // ���ǣ�����ǰ��ת�����1������������
47 "rep\n\t" // ������Ŀ�Ĵ��д��ʣ������Ŀ��ַ���
48 "stosb\n"
49 "2:"
50 ::"S" (src),"D" (dest),"c" (count):"si","di","ax","cx");
51 return dest; // ����Ŀ���ַ���ָ�롣
52 }
53
//// ��Դ�ַ���������Ŀ���ַ�����ĩβ����
// ������dest - Ŀ���ַ���ָ�룬src - Դ�ַ���ָ�롣
// %0 - esi(src)��%1 - edi(dest)��%2 - eax(0)��%3 - ecx(-1)��
54 extern inline char * strcat(char * dest,const char * src)
55 {
56 __asm__("cld\n\t" // �巽��λ��
57 "repne\n\t" // �Ƚ�al��es:[edi]�ֽڣ�������edi++��
58 "scasb\n\t" // ֱ���ҵ�Ŀ�Ĵ�����0���ֽڣ���ʱedi��ָ���1�ֽڡ�
59 "decl %1\n" // ��es:[edi]ָ��0ֵ�ֽڡ�
60 "1:\tlodsb\n\t" // ȡԴ�ַ����ֽ�ds:[esi]��al����esi++��
61 "stosb\n\t" // �����ֽڴ浽es:[edi]����edi++��
62 "testb %%al,%%al\n\t" // ���ֽ���0��
63 "jne 1b" // ���ǣ��������ת�����1���������������������
64 ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx");
65 return dest; // ����Ŀ���ַ���ָ�롣
66 }
67
//// ��Դ�ַ�����count���ֽڸ��Ƶ�Ŀ���ַ�����ĩβ���������һ���ַ���
// ������dest - Ŀ���ַ�����src - Դ�ַ�����count - �����Ƶ��ֽ�����
// %0 - esi(src)��%1 - edi(dest)��%2 - eax(0)��%3 - ecx(-1)��%4 - (count)��
68 extern inline char * strncat(char * dest,const char * src,int count)
69 {
70 __asm__("cld\n\t" // �巽��λ��
71 "repne\n\t" // �Ƚ�al��es:[edi]�ֽڣ�edi++��
72 "scasb\n\t" // ֱ���ҵ�Ŀ�Ĵ���ĩ��0ֵ�ֽڡ�
73 "decl %1\n\t" // ediָ���0ֵ�ֽڡ�
74 "movl %4,%3\n" // �������ֽ�����ecx��
75 "1:\tdecl %3\n\t" // ecx--����0��ʼ��������
76 "js 2f\n\t" // ecx <0 ?��������ǰ��ת�����2����
77 "lodsb\n\t" // ����ȡds:[esi]�����ֽ���al��esi++��
78 "stosb\n\t" // �洢��es:[edi]����edi++��
79 "testb %%al,%%al\n\t" // ���ֽ�ֵΪ0��
80 "jne 1b\n" // �����������ת�����1�����������ơ�
81 "2:\txorl %2,%2\n\t" // ��al���㡣
82 "stosb" // �浽es:[edi]����
83 ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count)
84 :"si","di","ax","cx");
85 return dest; // ����Ŀ���ַ���ָ�롣
86 }
87
//// ��һ���ַ�������һ���ַ������бȽϡ�
// ������cs - �ַ���1��ct - �ַ���2��
// %0 - eax(__res)����ֵ��%1 - edi(cs)�ַ���1ָ�룬%2 - esi(ct)�ַ���2ָ�롣
// ���أ������1 > ��2����1����1 = ��2����0����1 < ��2����-1��
// ��90�ж�����һ���ֲ��Ĵ����������ñ�������������eax�Ĵ����У��Ա��ڸ�Ч���ʺͲ�����
// ���ֶ�������ķ�����Ҫ������Ƕ�������С���ϸ˵���μ�gcc�ֲ���ָ���Ĵ����еı�������
88 extern inline int strcmp(const char * cs,const char * ct)
89 {
90 register int __res __asm__("ax"); // __res�ǼĴ�������(eax)��
91 __asm__("cld\n" // �巽��λ��
92 "1:\tlodsb\n\t" // ȡ�ַ���2���ֽ�ds:[esi]��al������esi++��
93 "scasb\n\t" // al���ַ���1���ֽ�es:[edi]���Ƚϣ�����edi++��
94 "jne 2f\n\t" // �������ȣ�����ǰ��ת�����2��
95 "testb %%al,%%al\n\t" // ���ֽ���0ֵ�ֽ����ַ�����β����
96 "jne 1b\n\t" // ���ǣ��������ת�����1�������Ƚϡ�
97 "xorl %%eax,%%eax\n\t" // �ǣ���ֵeax���㣬
98 "jmp 3f\n" // ��ǰ��ת�����3��������
99 "2:\tmovl $1,%%eax\n\t" // eax����1��
100 "jl 3f\n\t" // ��ǰ��Ƚ��д�2�ַ�<��1�ַ�������ֵ������
101 "negl %%eax\n" // ����eax = -eax�����ظ�ֵ��������
102 "3:"
103 :"=a" (__res):"D" (cs),"S" (ct):"si","di");
104 return __res; // ���رȽϽ����
105 }
106
//// �ַ���1���ַ���2��ǰcount���ַ����бȽϡ�
// ������cs - �ַ���1��ct - �ַ���2��count - �Ƚϵ��ַ�����
// %0 - eax(__res)����ֵ��%1 - edi(cs)��1ָ�룬%2 - esi(ct)��2ָ�룬%3 - ecx(count)��
// ���أ������1 > ��2����1����1 = ��2����0����1 < ��2����-1��
107 extern inline int strncmp(const char * cs,const char * ct,int count)
108 {
109 register int __res __asm__("ax"); // __res�ǼĴ�������(eax)��
110 __asm__("cld\n" // �巽��λ��
111 "1:\tdecl %3\n\t" // count--��
112 "js 2f\n\t" // ���count<0������ǰ��ת�����2��
113 "lodsb\n\t" // ȡ��2���ַ�ds:[esi]��al������esi++��
114 "scasb\n\t" // �Ƚ�al�봮1���ַ�es:[edi]������edi++��
115 "jne 3f\n\t" // �������ȣ�����ǰ��ת�����3��
116 "testb %%al,%%al\n\t" // ���ַ���NULL�ַ���
117 "jne 1b\n" // ���ǣ��������ת�����1�������Ƚϡ�
118 "2:\txorl %%eax,%%eax\n\t" // ��NULL�ַ�����eax���㣨����ֵ����
119 "jmp 4f\n" // ��ǰ��ת�����4��������
120 "3:\tmovl $1,%%eax\n\t" // eax����1��
121 "jl 4f\n\t" // ���ǰ��Ƚ��д�2�ַ�<��1�ַ�����1������
122 "negl %%eax\n" // ����eax = -eax�����ظ�ֵ��������
123 "4:"
124 :"=a" (__res):"D" (cs),"S" (ct),"c" (count):"si","di","cx");
125 return __res; // ���رȽϽ����
126 }
127
//// ���ַ�����Ѱ�ҵ�һ��ƥ����ַ���
// ������s - �ַ�����c - ��Ѱ�ҵ��ַ���
// %0 - eax(__res)��%1 - esi(�ַ���ָ��s)��%2 - eax(�ַ�c)��
// ���أ������ַ����е�һ�γ���ƥ���ַ���ָ�롣��û���ҵ�ƥ����ַ����ؿ�ָ�롣
128 extern inline char * strchr(const char * s,char c)
129 {
130 register char * __res __asm__("ax"); // __res�ǼĴ�������(eax)��
131 __asm__("cld\n\t" // �巽��λ��
132 "movb %%al,%%ah\n" // �����Ƚ��ַ��Ƶ�ah��
133 "1:\tlodsb\n\t" // ȡ�ַ������ַ�ds:[esi]��al������esi++��
134 "cmpb %%ah,%%al\n\t" // �ַ������ַ�al��ָ���ַ�ah��Ƚϡ�
135 "je 2f\n\t" // ����ȣ�����ǰ��ת�����2����
136 "testb %%al,%%al\n\t" // al���ַ���NULL�ַ��𣿣��ַ�����β����
137 "jne 1b\n\t" // �����ǣ��������ת�����1�������Ƚϡ�
138 "movl $1,%1\n" // �ǣ���˵��û���ҵ�ƥ���ַ���esi��1��
139 "2:\tmovl %1,%0\n\t" // ��ָ��ƥ���ַ���һ���ֽڴ���ָ��ֵ����eax
140 "decl %0" // ��ָ�����Ϊָ��ƥ����ַ���
141 :"=a" (__res):"S" (s),"0" (c):"si");
142 return __res; // ����ָ�롣
143 }
144
//// Ѱ���ַ�����ָ���ַ����һ�γ��ֵĵط��������������ַ�����
// ������s - �ַ�����c - ��Ѱ�ҵ��ַ���
// %0 - edx(__res)��%1 - edx(0)��%2 - esi(�ַ���ָ��s)��%3 - eax(�ַ�c)��
// ���أ������ַ��������һ�γ���ƥ���ַ���ָ�롣��û���ҵ�ƥ����ַ����ؿ�ָ�롣
145 extern inline char * strrchr(const char * s,char c)
146 {
147 register char * __res __asm__("dx"); // __res�ǼĴ�������(edx)��
148 __asm__("cld\n\t" // �巽��λ��
149 "movb %%al,%%ah\n" // ����Ѱ�ҵ��ַ��Ƶ�ah��
150 "1:\tlodsb\n\t" // ȡ�ַ������ַ�ds:[esi]��al������esi++��
151 "cmpb %%ah,%%al\n\t" // �ַ������ַ�al��ָ���ַ�ah���Ƚϡ�
152 "jne 2f\n\t" // ������ȣ�����ǰ��ת�����2����
153 "movl %%esi,%0\n\t" // ���ַ�ָ�뱣�浽edx�С�
154 "decl %0\n" // ָ�����һλ��ָ���ַ�����ƥ���ַ�����
155 "2:\ttestb %%al,%%al\n\t" // �Ƚϵ��ַ���0�𣨵��ַ���β����
156 "jne 1b" // �����������ת�����1���������Ƚϡ�
157 :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si");
158 return __res; // ����ָ�롣
159 }
160
//// ���ַ���1��Ѱ�ҵ�1���ַ����У����ַ������е��κ��ַ����������ַ���2�С�
// ������cs - �ַ���1ָ�룬ct - �ַ���2ָ�롣
// %0 - esi(__res)��%1 - eax(0)��%2 - ecx(-1)��%3 - esi(��1ָ��cs)��%4 - (��2ָ��ct)��
// �����ַ���1�а����ַ���2���κ��ַ������ַ����еij���ֵ��
161 extern inline int strspn(const char * cs, const char * ct)
162 {
163 register char * __res __asm__("si"); // __res�ǼĴ�������(esi)��
164 __asm__("cld\n\t" // �巽��λ��
165 "movl %4,%%edi\n\t" // ���ȼ��㴮2�ij��ȡ���2ָ�����edi�С�
166 "repne\n\t" // �Ƚ�al(0)�봮2�е��ַ���es:[edi]������edi++��
167 "scasb\n\t" // �������Ⱦͼ����Ƚ�(ecx�ݼ�)��
168 "notl %%ecx\n\t" // ecx��ÿλȡ����
169 "decl %%ecx\n\t" // ecx--���ô�2�ij���ֵ��
170 "movl %%ecx,%%edx\n" // ����2�ij���ֵ�ݷ���edx�С�
171 "1:\tlodsb\n\t" // ȡ��1�ַ�ds:[esi]��al������esi++��
172 "testb %%al,%%al\n\t" // ���ַ�����0ֵ�𣨴�1��β����
173 "je 2f\n\t" // ����ǣ�����ǰ��ת�����2����
174 "movl %4,%%edi\n\t" // ȡ��2ͷָ�����edi�С�
175 "movl %%edx,%%ecx\n\t" // �ٽ���2�ij���ֵ����ecx�С�
176 "repne\n\t" // �Ƚ�al�봮2���ַ�es:[edi]������edi++��
177 "scasb\n\t" // �������Ⱦͼ����Ƚϡ�
178 "je 1b\n" // �����ȣ��������ת�����1����
179 "2:\tdecl %0" // esi--��ָ�����һ�������ڴ�2�е��ַ���
180 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
181 :"ax","cx","dx","di");
182 return __res-cs; // �����ַ����еij���ֵ��
183 }
184
//// Ѱ���ַ���1�в������ַ���2���κ��ַ������ַ����С�
// ������cs - �ַ���1ָ�룬ct - �ַ���2ָ�롣
// %0 - esi(__res)��%1 - eax(0)��%2 - ecx(-1)��%3 - esi(��1ָ��cs)��%4 - (��2ָ��ct)��
// �����ַ���1�в������ַ���2���κ��ַ������ַ����еij���ֵ��
185 extern inline int strcspn(const char * cs, const char * ct)
186 {
187 register char * __res __asm__("si"); // __res�ǼĴ�������(esi)��
188 __asm__("cld\n\t" // �巽��λ��
189 "movl %4,%%edi\n\t" // ���ȼ��㴮2�ij��ȡ���2ָ�����edi�С�
190 "repne\n\t" // �Ƚ�al(0)�봮2�е��ַ���es:[edi]������edi++��
191 "scasb\n\t" // �������Ⱦͼ����Ƚ�(ecx�ݼ�)��
192 "notl %%ecx\n\t" // ecx��ÿλȡ����
193 "decl %%ecx\n\t" // ecx--���ô�2�ij���ֵ��
194 "movl %%ecx,%%edx\n" // ����2�ij���ֵ�ݷ���edx�С�
195 "1:\tlodsb\n\t" // ȡ��1�ַ�ds:[esi]��al������esi++��
196 "testb %%al,%%al\n\t" // ���ַ�����0ֵ�𣨴�1��β����
197 "je 2f\n\t" // ����ǣ�����ǰ��ת�����2����
198 "movl %4,%%edi\n\t" // ȡ��2ͷָ�����edi�С�
199 "movl %%edx,%%ecx\n\t" // �ٽ���2�ij���ֵ����ecx�С�
200 "repne\n\t" // �Ƚ�al�봮2���ַ�es:[edi]������edi++��
201 "scasb\n\t" // �������Ⱦͼ����Ƚϡ�
202 "jne 1b\n" // �������ȣ��������ת�����1����
203 "2:\tdecl %0" // esi--��ָ�����һ�������ڴ�2�е��ַ���
204 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
205 :"ax","cx","dx","di");
206 return __res-cs; // �����ַ����еij���ֵ��
207 }
208
//// ���ַ���1��Ѱ�����������ַ���2�е��κ��ַ���
// ������cs - �ַ���1��ָ�룬ct - �ַ���2��ָ�롣
// %0 -esi(__res)��%1 -eax(0)��%2 -ecx(0xffffffff)��%3 -esi(��1ָ��cs)��%4 -(��2ָ��ct)��
// �����ַ���1���������ַ���2���ַ���ָ�롣
209 extern inline char * strpbrk(const char * cs,const char * ct)
210 {
211 register char * __res __asm__("si"); // __res�ǼĴ�������(esi)��
212 __asm__("cld\n\t" // �巽��λ��
213 "movl %4,%%edi\n\t" // ���ȼ��㴮2�ij��ȡ���2ָ�����edi�С�
214 "repne\n\t" // �Ƚ�al(0)�봮2�е��ַ���es:[edi]������edi++��
215 "scasb\n\t" // �������Ⱦͼ����Ƚ�(ecx�ݼ�)��
216 "notl %%ecx\n\t" // ecx��ÿλȡ����
217 "decl %%ecx\n\t" // ecx--���ô�2�ij���ֵ��
218 "movl %%ecx,%%edx\n" // ����2�ij���ֵ�ݷ���edx�С�
219 "1:\tlodsb\n\t" // ȡ��1�ַ�ds:[esi]��al������esi++��
220 "testb %%al,%%al\n\t" // ���ַ�����0ֵ�𣨴�1��β����
221 "je 2f\n\t" // ����ǣ�����ǰ��ת�����2����
222 "movl %4,%%edi\n\t" // ȡ��2ͷָ�����edi�С�
223 "movl %%edx,%%ecx\n\t" // �ٽ���2�ij���ֵ����ecx�С�
224 "repne\n\t" // �Ƚ�al�봮2���ַ�es:[edi]������edi++��
225 "scasb\n\t" // �������Ⱦͼ����Ƚϡ�
226 "jne 1b\n\t" // �������ȣ��������ת�����1����
227 "decl %0\n\t" // esi--��ָ��һ�������ڴ�2�е��ַ���
228 "jmp 3f\n" // ��ǰ��ת�����3����
229 "2:\txorl %0,%0\n" // û���ҵ����������ģ�������ֵΪNULL��
230 "3:"
231 :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct)
232 :"ax","cx","dx","di");
233 return __res; // ����ָ��ֵ��
234 }
235
//// ���ַ���1��Ѱ����ƥ�������ַ���2���ַ�����
// ������cs - �ַ���1��ָ�룬ct - �ַ���2��ָ�롣
// %0 -eax(__res)��%1 -eax(0)��%2 -ecx(0xffffffff)��%3 -esi(��1ָ��cs)��%4 -(��2ָ��ct)��
// ���أ������ַ���1����ƥ���ַ���2���ַ���ָ�롣
236 extern inline char * strstr(const char * cs,const char * ct)
237 {
238 register char * __res __asm__("ax"); // __res�ǼĴ�������(eax)��
239 __asm__("cld\n\t" \ // �巽��λ��
240 "movl %4,%%edi\n\t" // ���ȼ��㴮2�ij��ȡ���2ָ�����edi�С�
241 "repne\n\t" // �Ƚ�al(0)�봮2�е��ַ���es:[edi]������edi++��
242 "scasb\n\t" // �������Ⱦͼ����Ƚ�(ecx�ݼ�)��
243 "notl %%ecx\n\t" // ecx��ÿλȡ����
244 "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */
/* ע�⣡���������Ϊ�գ�������Z��־ */ // �ô�2�ij���ֵ��
245 "movl %%ecx,%%edx\n" // ����2�ij���ֵ�ݷ���edx�С�
246 "1:\tmovl %4,%%edi\n\t" // ȡ��2ͷָ�����edi�С�
247 "movl %%esi,%%eax\n\t" // ����1��ָ�븴�Ƶ�eax�С�
248 "movl %%edx,%%ecx\n\t" // �ٽ���2�ij���ֵ����ecx�С�
249 "repe\n\t" // �Ƚϴ�1�ʹ�2�ַ�(ds:[esi],es:[edi])��esi++,edi++��
250 "cmpsb\n\t" // ����Ӧ�ַ���Ⱦ�һֱ�Ƚ���ȥ��
251 "je 2f\n\t" /* also works for empty string, see above */
/* �Կմ�ͬ����Ч�������� */ // ��ȫ��ȣ���ת�����2��
252 "xchgl %%eax,%%esi\n\t" // ��1ͷָ����esi���ȽϽ���Ĵ�1ָ����eax��
253 "incl %%esi\n\t" // ��1ͷָ��ָ����һ���ַ���
254 "cmpb $0,-1(%%eax)\n\t" // ��1ָ��(eax-1)��ָ�ֽ���0��
255 "jne 1b\n\t" // ������ת�����1�������Ӵ�1�ĵ�2���ַ���ʼ�Ƚϡ�
256 "xorl %%eax,%%eax\n\t" // ��eax����ʾû���ҵ�ƥ�䡣
257 "2:"
258 :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct)
259 :"cx","dx","di","si");
260 return __res; // ���رȽϽ����
261 }
262
//// �����ַ������ȡ�
// ������s - �ַ�����
// %0 - ecx(__res)��%1 - edi(�ַ���ָ��s)��%2 - eax(0)��%3 - ecx(0xffffffff)��
// ���أ������ַ����ij��ȡ�
263 extern inline int strlen(const char * s)
264 {
265 register int __res __asm__("cx"); // __res�ǼĴ�������(ecx)��
266 __asm__("cld\n\t" // �巽��λ��
267 "repne\n\t" // al(0)���ַ������ַ�es:[edi]�Ƚϣ�
268 "scasb\n\t" // ������Ⱦ�һֱ�Ƚϡ�
269 "notl %0\n\t" // ecxȡ����
270 "decl %0" // ecx--�����ַ����ó���ֵ��
271 :"=c" (__res):"D" (s),"a" (0),"0" (0xffffffff):"di");
272 return __res; // �����ַ�������ֵ��
273 }
274
275 extern char * ___strtok; // ������ʱ���ָ�����汻�����ַ���1(s)��ָ�롣
276
//// �����ַ���2�е��ַ����ַ���1�ָ�ɱ��(tokern)���С�
// ����1�����ǰ��������������(token)�����У����ɷָ���ַ���2�е�һ�������ַ�
// �ֿ�����һ�ε��� strtok()ʱ��������ָ���ַ���1�е�1��token���ַ���ָ�룬���ڷ�
// ��tokenʱ��һ null�ַ�д���ָ����������ʹ�� null ��Ϊ�ַ���1�ĵ��ã��������ַ�
// ������ɨ���ַ���1��ֱ��û��token Ϊֹ���ڲ�ͬ�ĵ��ù����У��ָ����2���Բ�ͬ��
// ������s - ���������ַ���1��ct - ���������ָ�����ַ���2��
// ��������%0 - ebx(__res)��%1 - esi(__strtok)��
// ������룺%2 - ebx(__strtok)��%3 - esi(�ַ���1ָ��s)��%4 - (�ַ���2ָ��ct)��
// ���أ������ַ���s�е�1��token�����û���ҵ�token����һ��nullָ�롣
// ����ʹ���ַ���sָ��Ϊnull�ĵ��ã�����ԭ�ַ���s��������һ��token��
277 extern inline char * strtok(char * s,const char * ct)
278 {
279 register char * __res __asm__("si");
280 __asm__("testl %1,%1\n\t" // ���Ȳ���esi(�ַ���1ָ��s)�Ƿ���NULL��
281 "jne 1f\n\t" // ������ǣ���������״ε��ñ���������ת���1��
282 "testl %0,%0\n\t" // ����NULL����ʾ�˴��Ǻ������ã���ebx(__strtok)��
283 "je 8f\n\t" // ���ebxָ����NULL�����ܴ�������ת������
284 "movl %0,%1\n" // ��ebxָ�븴�Ƶ�esi��
285 "1:\txorl %0,%0\n\t" // ��ebxָ�롣
286 "movl $-1,%%ecx\n\t" // ��ecx = 0xffffffff��
287 "xorl %%eax,%%eax\n\t" // ����eax��
288 "cld\n\t" // �巽��λ��
289 "movl %4,%%edi\n\t" // �������ַ���2�ij��ȡ�ediָ���ַ���2��
290 "repne\n\t" // ��al(0)��es:[edi]�Ƚϣ�����edi++��
291 "scasb\n\t" // ֱ���ҵ��ַ���2�Ľ���null�ַ��������ecx==0��
292 "notl %%ecx\n\t" // ��ecxȡ����
293 "decl %%ecx\n\t" // ecx--���õ��ַ���2�ij���ֵ��
294 "je 7f\n\t" /* empty delimeter-string */
/* �ָ���ַ����� */ // ����2����Ϊ0����ת���7��
295 "movl %%ecx,%%edx\n" // ����2�����ݴ���edx��
296 "2:\tlodsb\n\t" // ȡ��1���ַ�ds:[esi]��al������esi++��
297 "testb %%al,%%al\n\t" // ���ַ�Ϊ0ֵ��(��1����)��
298 "je 7f\n\t" // ����ǣ�����ת���7��
299 "movl %4,%%edi\n\t" // edi�ٴ�ָ��2�ס�
300 "movl %%edx,%%ecx\n\t" // ȡ��2�ij���ֵ���������ecx��
301 "repne\n\t" // ��al�д�1���ַ��봮2�������ַ��Ƚϣ�
302 "scasb\n\t" // �жϸ��ַ��Ƿ�Ϊ�ָ����
303 "je 2b\n\t" // �����ڴ�2���ҵ���ͬ�ַ����ָ����������ת���2��
304 "decl %1\n\t" // �����Ƿָ������1ָ��esiָ���ʱ�ĸ��ַ���
305 "cmpb $0,(%1)\n\t" // ���ַ���NULL�ַ���
306 "je 7f\n\t" // ���ǣ�����ת���7����
307 "movl %1,%0\n" // �����ַ���ָ��esi�����ebx��
308 "3:\tlodsb\n\t" // ȡ��1��һ���ַ�ds:[esi]��al������esi++��
309 "testb %%al,%%al\n\t" // ���ַ���NULL�ַ���
310 "je 5f\n\t" // ���ǣ���ʾ��1��������ת�����5��
311 "movl %4,%%edi\n\t" // edi�ٴ�ָ��2�ס�
312 "movl %%edx,%%ecx\n\t" // ��2����ֵ���������ecx��
313 "repne\n\t" // ��al�д�1���ַ��봮2��ÿ���ַ��Ƚϣ�
314 "scasb\n\t" // ����al�ַ��Ƿ��Ƿָ����
315 "jne 3b\n\t" // �����Ƿָ������ת���3����1����һ���ַ���
316 "decl %1\n\t" // ���Ƿָ������esi--��ָ��÷ָ���ַ���
317 "cmpb $0,(%1)\n\t" // �÷ָ����NULL�ַ���
318 "je 5f\n\t" // ���ǣ�����ת�����5��
319 "movb $0,(%1)\n\t" // �����ǣ��÷ָ����NULL�ַ��滻����
320 "incl %1\n\t" // esiָ��1����һ���ַ���Ҳ��ʣ�മ�ס�
321 "jmp 6f\n" // ��ת���6����
322 "5:\txorl %1,%1\n" // esi���㡣
323 "6:\tcmpb $0,(%0)\n\t" // ebxָ��ָ��NULL�ַ���
324 "jne 7f\n\t" // �����ǣ�����ת���7��
325 "xorl %0,%0\n" // ���ǣ�����ebx=NULL��
326 "7:\ttestl %0,%0\n\t" // ebxָ��ΪNULL��
327 "jne 8f\n\t" // ����������ת8�����������롣
328 "movl %0,%1\n" // ��esi��ΪNULL��
329 "8:"
330 :"=b" (__res),"=S" (___strtok)
331 :"0" (___strtok),"1" (s),"g" (ct)
332 :"ax","cx","dx","di");
333 return __res; // ����ָ����token��ָ�롣
334 }
335
//// �ڴ�鸴�ơ���Դ��ַsrc����ʼ����n���ֽڵ�Ŀ�ĵ�ַdest����
// ������dest - ���Ƶ�Ŀ�ĵ�ַ��src - ���Ƶ�Դ��ַ��n - �����ֽ�����
// %0 - ecx(n)��%1 - esi(src)��%2 - edi(dest)��
336 extern inline void * memcpy(void * dest,const void * src, int n)
337 {
338 __asm__("cld\n\t" // �巽��λ��
339 "rep\n\t" // �ظ�ִ�и���ecx���ֽڣ�
340 "movsb" // ��ds:[esi]��es:[edi]��esi++��edi++��
341 ::"c" (n),"S" (src),"D" (dest)
342 :"cx","si","di");
343 return dest; // ����Ŀ�ĵ�ַ��
344 }
345
//// �ڴ���ƶ���ͬ�ڴ�鸴�ƣ��������ƶ��ķ���
// ������dest - ���Ƶ�Ŀ�ĵ�ַ��src - ���Ƶ�Դ��ַ��n - �����ֽ�����
// ��dest<src��%0 - ecx(n)��%1 - esi(src)��%2 - edi(dest)��
// ����%0 - ecx(n)��%1 - esi(src+n-1)��%2 - edi(dest+n-1)��
// ����������Ϊ�˷�ֹ�ڸ���ʱ������ص����ǡ�
346 extern inline void * memmove(void * dest,const void * src, int n)
347 {
348 if (dest<src)
349 __asm__("cld\n\t" // �巽��λ��
350 "rep\n\t" // ��ds:[esi]��es:[edi]������esi++��edi++��
351 "movsb" // �ظ�ִ�и���ecx�ֽڡ�
352 ::"c" (n),"S" (src),"D" (dest)
353 :"cx","si","di");
354 else
355 __asm__("std\n\t" // �÷���λ����ĩ�˿�ʼ���ơ�
356 "rep\n\t" // ��ds:[esi]��es:[edi]������esi--��edi--��
357 "movsb" // ����ecx���ֽڡ�
358 ::"c" (n),"S" (src+n-1),"D" (dest+n-1)
359 :"cx","si","di");
360 return dest;
361 }
362
//// �Ƚ�n���ֽڵ������ڴ棨�����ַ���������ʹ����NULL�ֽ�Ҳ��ֹͣ�Ƚϡ�
// ������cs - �ڴ��1��ַ��ct - �ڴ��2��ַ��count - �Ƚϵ��ֽ�����
// %0 - eax(__res)��%1 - eax(0)��%2 - edi(�ڴ��1)��%3 - esi(�ڴ��2)��%4 - ecx(count)��
// ���أ�����1>��2 ����1����1<��2������-1����1==��2����0��
363 extern inline int memcmp(const void * cs,const void * ct,int count)
364 {
365 register int __res __asm__("ax"); // __res�ǼĴ���������
366 __asm__("cld\n\t" // �巽��λ��
367 "repe\n\t" // ���������ظ���
368 "cmpsb\n\t" // �Ƚ�ds:[esi]��es:[edi]�����ݣ�����esi++��edi++��
369 "je 1f\n\t" // �������ͬ������ת�����1������0(eax)ֵ
370 "movl $1,%%eax\n\t" // ����eax��1��
371 "jl 1f\n\t" // ���ڴ��2���ݵ�ֵ<�ڴ��1������ת���1��
372 "negl %%eax\n" // ����eax = -eax��
373 "1:"
374 :"=a" (__res):"0" (0),"D" (cs),"S" (ct),"c" (count)
375 :"si","di","cx");
376 return __res; // ���رȽϽ����
377 }
378
//// ��n�ֽڴ�С���ڴ��(�ַ���)��Ѱ��ָ���ַ���
// ������cs - ָ���ڴ���ַ��c - ָ�����ַ���count - �ڴ�鳤�ȡ�
// %0 - edi(__res)��%1 - eax(�ַ�c)��%2 - edi(�ڴ���ַcs)��%3 - ecx(�ֽ���count)��
// ���ص�һ��ƥ���ַ���ָ�룬���û���ҵ�����NULL�ַ���
379 extern inline void * memchr(const void * cs,char c,int count)
380 {
381 register void * __res __asm__("di"); // __res�ǼĴ���������
382 if (!count) // ����ڴ�鳤��==0����NULL��û���ҵ���
383 return NULL;
384 __asm__("cld\n\t" // �巽��λ��
385 "repne\n\t" // �����������ظ�ִ��������䣬
386 "scasb\n\t" // al���ַ���es:[edi]�ַ����Ƚϣ�����edi++��
387 "je 1f\n\t" // ����������ǰ��ת�����1����
388 "movl $1,%0\n" // ����edi����1��
389 "1:\tdecl %0" // ��ediָ���ҵ����ַ�������NULL����
390 :"=D" (__res):"a" (c),"D" (cs),"c" (count)
391 :"cx");
392 return __res; // �����ַ�ָ�롣
393 }
394
//// ���ַ���дָ�������ڴ�顣
// ���ַ�c��дsָ����ڴ�������count�ֽڡ�
// %0 - eax(�ַ�c)��%1 - edi(�ڴ��ַ)��%2 - ecx(�ֽ���count)��
395 extern inline void * memset(void * s,char c,int count)
396 {
397 __asm__("cld\n\t" // �巽��λ��
398 "rep\n\t" // �ظ�ecxָ���Ĵ�����ִ��
399 "stosb" // ��al���ַ�����es:[edi]�У�����edi++��
400 ::"a" (c),"D" (s),"c" (count)
401 :"cx","di");
402 return s;
403 }
404
405 #endif
406
1 #ifndef _TERMIOS_H
2 #define _TERMIOS_H
3
4 #include <sys/types.h>
5
6 #define TTY_BUF_SIZE 1024 // tty�еĻ��������ȡ�
7
8 /* 0x54 is just a magic number to make these relatively uniqe ('T') */
/* 0x54ֻ��һ��ħ����Ŀ����Ϊ��ʹ��Щ����Ψһ('T') */
9
// tty�豸��ioctl���������ioctl����������ڵ�λ���С�
// ��������TC[*]�����tty�������
// ȡ��Ӧ�ն�termios�ṹ�е���Ϣ(�μ�tcgetattr())��
10 #define TCGETS 0x5401
// ������Ӧ�ն�termios�ṹ�е���Ϣ(�μ�tcsetattr()��TCSANOW)��
11 #define TCSETS 0x5402
// �������ն�termios����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ�����(�ľ�)�������IJ���
// ��Ӱ����������������Ҫʹ��������ʽ(�μ�tcsetattr()��TCSADRAINѡ��)��
12 #define TCSETSW 0x5403
// ������termios����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ����꣬����ˢ��(���)������С�
// �����ã��μ�tcsetattr()��TCSAFLUSHѡ���
13 #define TCSETSF 0x5404
// ȡ��Ӧ�ն�termio�ṹ�е���Ϣ(�μ�tcgetattr())��
14 #define TCGETA 0x5405
// ������Ӧ�ն�termio�ṹ�е���Ϣ(�μ�tcsetattr()��TCSANOWѡ��)��
15 #define TCSETA 0x5406
// �������ն�termio����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ�����(�ľ�)�������IJ���
// ��Ӱ����������������Ҫʹ��������ʽ(�μ�tcsetattr()��TCSADRAINѡ��)��
16 #define TCSETAW 0x5407
// ������termio����Ϣ֮ǰ����Ҫ�ȵȴ�����������������ݴ����꣬����ˢ��(���)������С�
// �����ã��μ�tcsetattr()��TCSAFLUSHѡ���
17 #define TCSETAF 0x5408
// �ȴ�������д������(��)��������ֵ��0������һ��break���μ�tcsendbreak()��tcdrain()����
18 #define TCSBRK 0x5409
// ��ʼ/ֹͣ���ơ��������ֵ��0�����������������1�������¿������������������2��
// ��������룻�����3�������¿�����������루�μ�tcflow()����
19 #define TCXONC 0x540A
// ˢ����д�������û���ͻ����յ���û�ж����ݡ����������0����ˢ��(���)������У����
// ��1����ˢ��������У������2����ˢ�������������У��μ�tcflush()����
20 #define TCFLSH 0x540B
// ��������TIOC[*]�����tty ��������������
// �����ն˴�����·ר��ģʽ��
21 #define TIOCEXCL 0x540C
// ��λ�ն˴�����·ר��ģʽ��
22 #define TIOCNXCL 0x540D
// ����ttyΪ�����նˡ�(TIOCNOTTY - ��ֹttyΪ�����ն�)��
23 #define TIOCSCTTY 0x540E
// ��ȡָ���ն��豸���̵���id���μ�tcgetpgrp()���ó�������������"Terminal IO Control
// Get PGRP "����д����ȡǰ̨������ID��
24 #define TIOCGPGRP 0x540F
// ����ָ���ն��豸���̵���id(�μ�tcsetpgrp())��
25 #define TIOCSPGRP 0x5410
// ������������л�δ�ͳ����ַ�����
26 #define TIOCOUTQ 0x5411
// ģ���ն����롣��������һ��ָ���ַ���ָ����Ϊ����������װ���ַ������ն��ϼ���ġ��û�
// �����ڸÿ����ն��Ͼ��г����û�Ȩ����ж�����Ȩ�ޡ�
27 #define TIOCSTI 0x5412
// ��ȡ�ն��豸���ڴ�С��Ϣ���μ�winsize�ṹ����
28 #define TIOCGWINSZ 0x5413
// �����ն��豸���ڴ�С��Ϣ���μ�winsize�ṹ����
29 #define TIOCSWINSZ 0x5414
// ����modem״̬�������ߵĵ�ǰ״̬����λ��־�����μ�����185-196�У���
30 #define TIOCMGET 0x5415
// ���õ���modem״̬�������ߵ�״̬(true��false)(Individual control line Set)��
31 #define TIOCMBIS 0x5416
// ��λ����modem״̬�������ߵ�״̬(Individual control line clear)��
32 #define TIOCMBIC 0x5417
// ����modem״̬���ߵ�״̬�����ijһ����λ��λ����modem��Ӧ��״̬���߽���Ϊ��Ч��
33 #define TIOCMSET 0x5418
// ��ȡ�����ز�����־(1 - ������0 - �ر�)��
// ���ڱ������ӵ��ն˻������豸�������ز���־�ǿ����ģ�����ʹ��modem��·���ն˻��豸
// ���ǹرյġ�Ϊ����ʹ�������� ioctl���ã�tty��·Ӧ������ O_NDELAY ��ʽ�ģ�����
// open()�Ͳ���ȴ��ز���
34 #define TIOCGSOFTCAR 0x5419
// ���������ز�����־(1 - ������0 - �ر�)��
35 #define TIOCSSOFTCAR 0x541A
// ������������л�δȡ���ַ�����Ŀ��
36 #define FIONREAD 0x541B
37 #define TIOCINQ FIONREAD
38
// ���ڴ�С(Window size)���Խṹ���ڴ��ڻ����п����ڻ�����Ļ��Ӧ�ó���
// ioctls�е�TIOCGWINSZ��TIOCSWINSZ��������ȡ��������Щ��Ϣ��
39 struct winsize {
40 unsigned short ws_row; // �����ַ�������
41 unsigned short ws_col; // �����ַ�������
42 unsigned short ws_xpixel; // ���ڿ��ȣ�����ֵ��
43 unsigned short ws_ypixel; // ���ڸ߶ȣ�����ֵ��
44 };
45
// AT&TϵͳV��termio�ṹ��
46 #define NCC 8 // termio�ṹ�п����ַ�����ij��ȡ�
47 struct termio {
48 unsigned short c_iflag; /* input mode flags */ // ����ģʽ��־��
49 unsigned short c_oflag; /* output mode flags */ // ���ģʽ��־��
50 unsigned short c_cflag; /* control mode flags */ // ����ģʽ��־��
51 unsigned short c_lflag; /* local mode flags */ // ����ģʽ��־��
52 unsigned char c_line; /* line discipline */ // ��·��̣����ʣ���
53 unsigned char c_cc[NCC]; /* control characters */ // �����ַ����顣
54 };
55
// POSIX��termios�ṹ��
56 #define NCCS 17 // termios�ṹ�п����ַ����鳤�ȡ�
57 struct termios {
58 tcflag_t c_iflag; /* input mode flags */ // ����ģʽ��־��
59 tcflag_t c_oflag; /* output mode flags */ // ���ģʽ��־��
60 tcflag_t c_cflag; /* control mode flags */ // ����ģʽ��־��
61 tcflag_t c_lflag; /* local mode flags */ // ����ģʽ��־��
62 cc_t c_line; /* line discipline */ // ��·��̣����ʣ���
63 cc_t c_cc[NCCS]; /* control characters */ // �����ַ����顣
64 };
65
// �����ǿ����ַ�����c_cc[]���������ֵ���������ʼֵ������include/linux/tty.h�С�
// ������Ը�����������е�ֵ�����������_POSIX_VDISABLE��\0������ô������ijһ��ֵ
// ���� _POSIX_VDISABLE ��ֵʱ����ʾ��ֹʹ����������Ӧ�������ַ���
66 /* c_cc characters */ /* c_cc�����е��ַ� */
67 #define VINTR 0 // c_cc[VINTR] = INTR (^C)��\003���ж��ַ���
68 #define VQUIT 1 // c_cc[VQUIT] = QUIT (^\)��\034���˳��ַ���
69 #define VERASE 2 // c_cc[VERASE] = ERASE (^H)��\177�������ַ���
70 #define VKILL 3 // c_cc[VKILL] = KILL (^U)��\025����ֹ�ַ���ɾ���У���
71 #define VEOF 4 // c_cc[VEOF] = EOF (^D)��\004���ļ������ַ���
72 #define VTIME 5 // c_cc[VTIME] = TIME (\0)��\0�� ��ʱ��ֵ(�μ�����˵��)��
73 #define VMIN 6 // c_cc[VMIN] = MIN (\1)��\1�� ��ʱ��ֵ��
74 #define VSWTC 7 // c_cc[VSWTC] = SWTC (\0)��\0�� �����ַ���
75 #define VSTART 8 // c_cc[VSTART] = START (^Q)��\021����ʼ�ַ���
76 #define VSTOP 9 // c_cc[VSTOP] = STOP (^S)��\023��ֹͣ�ַ���
77 #define VSUSP 10 // c_cc[VSUSP] = SUSP (^Z)��\032�������ַ���
78 #define VEOL 11 // c_cc[VEOL] = EOL (\0)��\0�� �н����ַ���
79 #define VREPRINT 12 // c_cc[VREPRINT] = REPRINT (^R)��\022������ʾ�ַ���
80 #define VDISCARD 13 // c_cc[VDISCARD] = DISCARD (^O)��\017�������ַ���
81 #define VWERASE 14 // c_cc[VWERASE] = WERASE (^W)��\027�����ʲ����ַ���
82 #define VLNEXT 15 // c_cc[VLNEXT] = LNEXT (^V)��\026����һ���ַ���
83 #define VEOL2 16 // c_cc[VEOL2] = EOL2 (\0)��\0�� �н����ַ�2��
84
// termios�ṹ����ģʽ�ֶ�c_iflag���ֱ�־�ķ��ų�����
85 /* c_iflag bits */ /* c_iflag����λ */
86 #define IGNBRK 0000001 // ����ʱ����BREAK������
87 #define BRKINT 0000002 // ��BREAKʱ����SIGINT�źš�
88 #define IGNPAR 0000004 // ������żУ��������ַ���
89 #define PARMRK 0000010 // �����żУ�����
90 #define INPCK 0000020 // ����������żУ�顣
91 #define ISTRIP 0000040 // �����ַ���8λ��
92 #define INLCR 0000100 // ����ʱ�����з�NLӳ��ɻس���CR��
93 #define IGNCR 0000200 // ���Իس���CR��
94 #define ICRNL 0000400 // ������ʱ���س���CRӳ��ɻ��з�NL��
95 #define IUCLC 0001000 // ������ʱ����д�ַ�ת����Сд�ַ���
96 #define IXON 0002000 // ������ʼ/ֹͣ��XON/XOFF��������ơ�
97 #define IXANY 0004000 // �����κ��ַ����������
98 #define IXOFF 0010000 // ������ʼ/ֹͣ��XON/XOFF��������ơ�
99 #define IMAXBEL 0020000 // ���������ʱ���塣
100
// termios�ṹ�����ģʽ�ֶ�c_oflag���ֱ�־�ķ��ų�����
101 /* c_oflag bits */ /* c_oflag����λ */
102 #define OPOST 0000001 // ִ�����������
103 #define OLCUC 0000002 // �����ʱ��Сд�ַ�ת���ɴ�д�ַ���
104 #define ONLCR 0000004 // �����ʱ�����з�NLӳ��ɻس�-���з�CR-NL��
105 #define OCRNL 0000010 // �����ʱ���س���CRӳ��ɻ��з�NL��
106 #define ONOCR 0000020 // ��0�в�����س���CR��
107 #define ONLRET 0000040 // ���з�NLִ�лس����Ĺ��ܡ�
108 #define OFILL 0000100 // �ӳ�ʱʹ������ַ�����ʹ��ʱ���ӳ١�
109 #define OFDEL 0000200 // ����ַ���ASCII��DEL�����δ���ã���ʹ��ASCII NULL��
110 #define NLDLY 0000400 // ѡ�����ӳ١�
111 #define NL0 0000000 // �����ӳ�����0��
112 #define NL1 0000400 // �����ӳ�����1��
113 #define CRDLY 0003000 // ѡ��س��ӳ١�
114 #define CR0 0000000 // �س��ӳ�����0��
115 #define CR1 0001000 // �س��ӳ�����1��
116 #define CR2 0002000 // �س��ӳ�����2��
117 #define CR3 0003000 // �س��ӳ�����3��
118 #define TABDLY 0014000 // ѡ��ˮƽ�Ʊ��ӳ١�
119 #define TAB0 0000000 // ˮƽ�Ʊ��ӳ�����0��
120 #define TAB1 0004000 // ˮƽ�Ʊ��ӳ�����1��
121 #define TAB2 0010000 // ˮƽ�Ʊ��ӳ�����2��
122 #define TAB3 0014000 // ˮƽ�Ʊ��ӳ�����3��
123 #define XTABS 0014000 // ���Ʊ���TAB���ɿո�ֵ��ʾ�ո�����
124 #define BSDLY 0020000 // ѡ���˸��ӳ١�
125 #define BS0 0000000 // �˸��ӳ�����0��
126 #define BS1 0020000 // �˸��ӳ�����1��
127 #define VTDLY 0040000 // �����Ʊ��ӳ١�
128 #define VT0 0000000 // �����Ʊ��ӳ�����0��
129 #define VT1 0040000 // �����Ʊ��ӳ�����1��
130 #define FFDLY 0040000 // ѡ��ҳ�ӳ١�
131 #define FF0 0000000 // ��ҳ�ӳ�����0��
132 #define FF1 0040000 // ��ҳ�ӳ�����1��
133
// termios�ṹ�п���ģʽ��־�ֶ�c_cflag��־�ķ��ų�����8����������
134 /* c_cflag bit meaning */ /* c_cflag ����λ�ĺ��� */
135 #define CBAUD 0000017 // ��������λ�����롣
136 #define B0 0000000 /* hang up */ /* �Ҷ���· */
137 #define B50 0000001 // ������ 50��
138 #define B75 0000002 // ������ 75��
139 #define B110 0000003 // ������ 110��
140 #define B134 0000004 // ������ 134��
141 #define B150 0000005 // ������ 150��
142 #define B200 0000006 // ������ 200��
143 #define B300 0000007 // ������ 300��
144 #define B600 0000010 // ������ 600��
145 #define B1200 0000011 // ������ 1200��
146 #define B1800 0000012 // ������ 1800��
147 #define B2400 0000013 // ������ 2400��
148 #define B4800 0000014 // ������ 4800��
149 #define B9600 0000015 // ������ 9600��
150 #define B19200 0000016 // ������ 19200��
151 #define B38400 0000017 // ������ 38400��
152 #define EXTA B19200 // ��չ������A��
153 #define EXTB B38400 // ��չ������B��
154 #define CSIZE 0000060 // �ַ�λ���������롣
155 #define CS5 0000000 // ÿ�ַ�5����λ��
156 #define CS6 0000020 // ÿ�ַ�6����λ��
157 #define CS7 0000040 // ÿ�ַ�7����λ��
158 #define CS8 0000060 // ÿ�ַ�8����λ��
159 #define CSTOPB 0000100 // ��������ֹͣλ��������1����
160 #define CREAD 0000200 // �������ա�
161 #define PARENB 0000400 // �������ʱ������żλ������ʱ������żУ�顣
162 #define PARODD 0001000 // ����/����У������У�顣
163 #define HUPCL 0002000 // �����̹رպ�Ҷϡ�
164 #define CLOCAL 0004000 // ���Ե��ƽ����(modem)������·��
165 #define CIBAUD 03600000 /* input baud rate (not used) */ /* ���벨����(δʹ��) */
166 #define CRTSCTS 020000000000 /* flow control */ /* ������ */
167
// termios�ṹ�б���ģʽ��־�ֶ�c_lflag�ķ��ų�����
168 /* c_lflag bits */ /* c_lflag����λ */
169 #define ISIG 0000001 // ���յ��ַ�INTR��QUIT��SUSP��DSUSP��������Ӧ���źš�
170 #define ICANON 0000002 // �����淶ģʽ����ģʽ����
171 #define XCASE 0000004 // ��������ICANON�����ն��Ǵ�д�ַ��ġ�
172 #define ECHO 0000010 // ���������ַ���
173 #define ECHOE 0000020 // ��������ICANON����ERASE/WERASE������ǰһ�ַ�/���ʡ�
174 #define ECHOK 0000040 // ��������ICANON����KILL�ַ���������ǰ�С�
175 #define ECHONL 0000100 // ��������ICANON����ʹECHOû�п���Ҳ����NL�ַ���
176 #define NOFLSH 0000200 // ������SIGINT��SIGQUIT�ź�ʱ��ˢ������������У���
// ����SIGSUSP�ź�ʱ��ˢ��������С�
177 #define TOSTOP 0000400 // ����SIGTTOU�źŵ���̨���̵Ľ����飬�ú�̨������ͼд
// �Լ��Ŀ����նˡ�
178 #define ECHOCTL 0001000 // ��������ECHO�����TAB��NL��START��STOP�����ASCII
// �����źŽ������Գ���^Xʽ����Xֵ�ǿ��Ʒ�+0x40��
179 #define ECHOPRT 0002000 // ��������ICANON��IECHO�����ַ��ڲ���ʱ����ʾ��
180 #define ECHOKE 0004000 // ��������ICANON����KILLͨ���������ϵ������ַ������ԡ�
181 #define FLUSHO 0010000 // �����ˢ�¡�ͨ������DISCARD�ַ����ñ�־����ת��
182 #define PENDIN 0040000 // ����һ���ַ��Ƕ�ʱ����������е������ַ��������ԡ�
183 #define IEXTEN 0100000 // ����ʵ��ʱ��������봦����
184
185 /* modem lines */ /* modem��·�źŷ��ų��� */
186 #define TIOCM_LE 0x001 // ��·����(Line Enable)��
187 #define TIOCM_DTR 0x002 // �����ն˾���(Data Terminal Ready)��
188 #define TIOCM_RTS 0x004 // ������(Request to Send)��
189 #define TIOCM_ST 0x008 // �������ݷ���(Serial Transfer)��[??]
190 #define TIOCM_SR 0x010 // �������ݽ���(Serial Receive)��[??]
191 #define TIOCM_CTS 0x020 // �������(Clear To Send)��
192 #define TIOCM_CAR 0x040 // �ز����(Carrier Detect)��
193 #define TIOCM_RNG 0x080 // ����ָʾ(Ring indicate)��
194 #define TIOCM_DSR 0x100 // �����豸����(Data Set Ready)��
195 #define TIOCM_CD TIOCM_CAR
196 #define TIOCM_RI TIOCM_RNG
197
198 /* tcflow() and TCXONC use these */ /* tcflow()��TCXONCʹ����Щ���ų��� */
199 #define TCOOFF 0 // �����������"Terminal Control Output OFF"�������
200 #define TCOON 1 // ����������������
201 #define TCIOFF 2 // ϵͳ����һ��STOP�ַ���ʹ�豸ֹͣ��ϵͳ�������ݡ�
202 #define TCION 3 // ϵͳ����һ��START�ַ���ʹ�豸��ʼ��ϵͳ�������ݡ�
203
204 /* tcflush() and TCFLSH use these */ /* tcflush()��TCFLSHʹ����Щ���ų��� */
205 #define TCIFLUSH 0 // ����յ������ݵ�������
206 #define TCOFLUSH 1 // ����д�����ݵ������͡�
207 #define TCIOFLUSH 2 // ����յ������ݵ�����������д�����ݵ������͡�
208
209 /* tcsetattr uses these */ /* tcsetattr()ʹ����Щ���ų��� */
210 #define TCSANOW 0 // �ı�����������
211 #define TCSADRAIN 1 // �ı���������д�����������֮������
212 #define TCSAFLUSH 2 // �ı���������д�����������֮���������н��յ���
// ��û�ж�ȡ�����ݱ�����֮������
213
// ������Щ�����ڱ��뻷���ĺ�����libc.a��ʵ�֣��ں���û�С��ں�����ʵ���У���Щ����ͨ��
// ����ϵͳ����ioctl()��ʵ�֡��й�ioctl()ϵͳ���ã���μ�fs/ioctl.c����
// ����termios_p��ָtermios�ṹ�еĽ��ղ����ʡ�
214 extern speed_t cfgetispeed(struct termios *termios_p);
// ����termios_p��ָtermios�ṹ�еķ��Ͳ����ʡ�
215 extern speed_t cfgetospeed(struct termios *termios_p);
// ��termios_p��ָtermios�ṹ�еĽ��ղ���������Ϊspeed��
216 extern int cfsetispeed(struct termios *termios_p, speed_t speed);
// ��termios_p��ָtermios�ṹ�еķ��Ͳ���������Ϊspeed��
217 extern int cfsetospeed(struct termios *termios_p, speed_t speed);
// �ȴ�fildes��ָ������д������ݱ����ͳ�ȥ��
218 extern int tcdrain(int fildes);
// ����/����fildes��ָ�������ݵĽ��պͷ��͡�
219 extern int tcflow(int fildes, int action);
// ����fildesָ������������д����û�����Լ��������յ�����û�ж�ȡ�����ݡ�
220 extern int tcflush(int fildes, int queue_selector);
// ��ȡ����fildes��Ӧ����IJ����������䱣����termios_p��ָ�ĵط���
221 extern int tcgetattr(int fildes, struct termios *termios_p);
// ����ն�ʹ���첽�������ݴ��䣬����һ��ʱ������������һϵ��0ֵ����λ��
222 extern int tcsendbreak(int fildes, int duration);
// ʹ��termios�ṹָ��termios_p��ָ�����ݣ��������ն���صIJ�����
223 extern int tcsetattr(int fildes, int optional_actions,
224 struct termios *termios_p);
225
226 #endif
227
1 #ifndef _TIME_H
2 #define _TIME_H
3
4 #ifndef _TIME_T
5 #define _TIME_T
6 typedef long time_t; // ��GMT 1970��1��1����ҹ0ʱ��ʼ�Ƶ�ʱ�䣨�룩��
7 #endif
8
9 #ifndef _SIZE_T
10 #define _SIZE_T
11 typedef unsigned int size_t;
12 #endif
13
14 #ifndef NULL
15 #define NULL ((void *) 0)
16 #endif
17
18 #define CLOCKS_PER_SEC 100 // ϵͳʱ�ӵδ�Ƶ�ʣ�100HZ��
19
20 typedef long clock_t; // �ӽ��̿�ʼִ�м����ϵͳ������ʱ�ӵδ�����
21
22 struct tm {
23 int tm_sec; // ���� [0��59]��
24 int tm_min; // ������ [ 0��59]��
25 int tm_hour; // Сʱ�� [0��59]��
26 int tm_mday; // 1���µ����� [0��31]��
27 int tm_mon; // 1�����·� [0��11]��
28 int tm_year; // ��1900�꿪ʼ��������
29 int tm_wday; // 1�����е�ij�� [0��6]�������� =0����
30 int tm_yday; // 1���е�ij�� [0��365]��
31 int tm_isdst; // ����ʱ��־������ - ʹ�ã�0 - û��ʹ�ã����� - ��Ч��
32 };
33
// �ж��Ƿ�Ϊ����ĺꡣ
34 #define __isleap(year) \
35 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 1000 == 0))
36
// �������й�ʱ������ĺ���ԭ�͡�
// ȷ��������ʹ��ʱ�䡣���س������ô�����ʱ�䣨�δ������Ľ���ֵ��
37 clock_t clock(void);
// ȡʱ�䣨�����������ش�1970.1.1:0:0:0��ʼ����������Ϊ����ʱ�䣩��
38 time_t time(time_t * tp);
// ����ʱ������ʱ��time2��time1֮�侭����������
39 double difftime(time_t time2, time_t time1);
// ��tm�ṹ��ʾ��ʱ��ת��������ʱ�䡣
40 time_t mktime(struct tm * tp);
41
// ��tm�ṹ��ʾ��ʱ��ת����һ���ַ���������ָ��ô���ָ�롣
42 char * asctime(const struct tm * tp);
// ������ʱ��ת����һ���ַ�����ʽ���硰Wed Jun 30 21:49:08:1993\n����
43 char * ctime(const time_t * tp);
// ������ʱ��ת����tm�ṹ��ʾ��UTCʱ�䣨UTC - ����ʱ�����Universal Time Code����
44 struct tm * gmtime(const time_t *tp);
// ������ʱ��ת����tm�ṹ��ʾ��ָ��ʱ��(Time Zone)��ʱ�䡣
45 struct tm *localtime(const time_t * tp);
// ��tm�ṹ��ʾ��ʱ�����ø�ʽ�ַ���fmtת�������Ϊsmax���ַ�����������洢��s�С�
46 size_t strftime(char * s, size_t smax, const char * fmt, const struct tm * tp);
// ��ʼ��ʱ��ת����Ϣ��ʹ�û�������TZ����zname�������г�ʼ����
// ����ʱ����ص�ʱ��ת�������н��Զ����øú�����
47 void tzset(void);
48
49 #endif
50
1 #ifndef _UNISTD_H
2 #define _UNISTD_H
3
4 /* ok, this may be a joke, but I'm working on it */
/* ok, ��Ҳ���Ǹ���Ц�������������ִ��� */
// ������ų���ָ������IEEE��1003.1ʵ�ֵİ汾�ţ���һ������ֵ��
5 #define _POSIX_VERSION 198808L
6
// chown()��fchown()��ʹ�������ڽ��̵�Ȩ�ޡ�/* ֻ�г����û�����ִ��chown������..��*/
7 #define _POSIX_CHOWN_RESTRICTED /* only root can do a chown (I think..) */
// ����(NAME_MAX)��·�������������������Զ��ضϡ�/* ·�������ضϣ������뿴�ں˴��룩*/
8 #define _POSIX_NO_TRUNC /* no pathname truncation (but see in kernel) */
// ����������Ž�������ַ�ֵ����ֵ����ֹ�ն˶���Ĵ�����/* ��ֹ��^C�������ַ� */
// _POSIX_VDISABLE���ڿ����ն�ijЩ�����ַ��Ĺ��ܡ���һ���ն�termios�ṹ��c_cc[]
// ����ij���ַ�����ֵ����_POSIX_VDISABLE��ֵʱ����ʾ��ֹʹ����Ӧ�������ַ���
9 #define _POSIX_VDISABLE '\0' /* character to disable things like ^C */
// ϵͳʵ��֧����ҵ���ơ�
10 #define _POSIX_JOB_CONTROL
// ÿ�����̶���һ�����set-user-ID��һ�����set-group-ID�� /* �Ѿ�ʵ�֡� */
11 #define _POSIX_SAVED_IDS /* Implemented, for whatever good it is */
12
13 #define STDIN_FILENO 0 // �������ļ���������������š�
14 #define STDOUT_FILENO 1 // ������ļ�����š�
15 #define STDERR_FILENO 2 // �������ļ�����š�
16
17 #ifndef NULL
18 #define NULL ((void *)0) // �����ָ�롣
19 #endif
20
21 /* access */ /* ����� */
// ���¶���ķ��ų�������access()������
22 #define F_OK 0 // ����ļ��Ƿ���ڡ�
23 #define X_OK 1 // ����Ƿ��ִ�У���������
24 #define W_OK 2 // ����Ƿ��д��
25 #define R_OK 4 // ����Ƿ�ɶ���
26
27 /* lseek */ /* �ļ�ָ���ض�λ */
// ���·��ų�������lseek()��fcntl()������
28 #define SEEK_SET 0 // ���ļ���дָ������Ϊƫ��ֵ��
29 #define SEEK_CUR 1 // ���ļ���дָ������Ϊ��ǰֵ����ƫ��ֵ��
30 #define SEEK_END 2 // ���ļ���дָ������Ϊ�ļ����ȼ���ƫ��ֵ��
31
32 /* _SC stands for System Configuration. We don't use them much */
/* _SC��ʾϵͳ���á����Ǻ���ʹ�� */
// ����ķ��ų�������sysconf()������
33 #define _SC_ARG_MAX 1 // ����������
34 #define _SC_CHILD_MAX 2 // �ӽ����������
35 #define _SC_CLOCKS_PER_SEC 3 // ÿ��δ�����
36 #define _SC_NGROUPS_MAX 4 // ���������
37 #define _SC_OPEN_MAX 5 // ���������
38 #define _SC_JOB_CONTROL 6 // ��ҵ���ơ�
39 #define _SC_SAVED_IDS 7 // ����ı�ʶ����
40 #define _SC_VERSION 8 // �汾��
41
42 /* more (possibly) configurable things - now pathnames */
/* ����ģ����ܵģ������ò��� - ��������·���� */
// ����ķ��ų�������pathconf()������
43 #define _PC_LINK_MAX 1 // �����������
44 #define _PC_MAX_CANON 2 // ��������
45 #define _PC_MAX_INPUT 3 // ������볤�ȡ�
46 #define _PC_NAME_MAX 4 // ������ȡ�
47 #define _PC_PATH_MAX 5 // ·����ȡ�
48 #define _PC_PIPE_BUF 6 // �ܵ������С��
49 #define _PC_NO_TRUNC 7 // �ļ������ضϡ�
50 #define _PC_VDISABLE 8 //
51 #define _PC_CHOWN_RESTRICTED 9 // �ı��������ޡ�
52
53 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
54 #include <sys/time.h>
55 #include <sys/times.h> // �����˽���������ʱ��ṹtms�Լ�times()����ԭ�͡�
56 #include <sys/utsname.h> // ϵͳ���ƽṹͷ�ļ���
57 #include <sys/resource.h>
58 #include <utime.h> // �û�ʱ��ͷ�ļ��������˷��ʺ���ʱ��ṹ�Լ�utime()ԭ�͡�
59
60 #ifdef __LIBRARY__
61
// ������ʵ�ֵ�ϵͳ���÷��ų���������ϵͳ���ú�����������ֵ(�μ�include/linux/sys.h) ��
62 #define __NR_setup 0 /* used only by init, to get system going */
63 #define __NR_exit 1 /* __NR_setup�����ڳ�ʼ����������ϵͳ */
64 #define __NR_fork 2
65 #define __NR_read 3
66 #define __NR_write 4
67 #define __NR_open 5
68 #define __NR_close 6
69 #define __NR_waitpid 7
70 #define __NR_creat 8
71 #define __NR_link 9
72 #define __NR_unlink 10
73 #define __NR_execve 11
74 #define __NR_chdir 12
75 #define __NR_time 13
76 #define __NR_mknod 14
77 #define __NR_chmod 15
78 #define __NR_chown 16
79 #define __NR_break 17
80 #define __NR_stat 18
81 #define __NR_lseek 19
82 #define __NR_getpid 20
83 #define __NR_mount 21
84 #define __NR_umount 22
85 #define __NR_setuid 23
86 #define __NR_getuid 24
87 #define __NR_stime 25
88 #define __NR_ptrace 26
89 #define __NR_alarm 27
90 #define __NR_fstat 28
91 #define __NR_pause 29
92 #define __NR_utime 30
93 #define __NR_stty 31
94 #define __NR_gtty 32
95 #define __NR_access 33
96 #define __NR_nice 34
97 #define __NR_ftime 35
98 #define __NR_sync 36
99 #define __NR_kill 37
100 #define __NR_rename 38
101 #define __NR_mkdir 39
102 #define __NR_rmdir 40
103 #define __NR_dup 41
104 #define __NR_pipe 42
105 #define __NR_times 43
106 #define __NR_prof 44
107 #define __NR_brk 45
108 #define __NR_setgid 46
109 #define __NR_getgid 47
110 #define __NR_signal 48
111 #define __NR_geteuid 49
112 #define __NR_getegid 50
113 #define __NR_acct 51
114 #define __NR_phys 52
115 #define __NR_lock 53
116 #define __NR_ioctl 54
117 #define __NR_fcntl 55
118 #define __NR_mpx 56
119 #define __NR_setpgid 57
120 #define __NR_ulimit 58
121 #define __NR_uname 59
122 #define __NR_umask 60
123 #define __NR_chroot 61
124 #define __NR_ustat 62
125 #define __NR_dup2 63
126 #define __NR_getppid 64
127 #define __NR_getpgrp 65
128 #define __NR_setsid 66
129 #define __NR_sigaction 67
130 #define __NR_sgetmask 68
131 #define __NR_ssetmask 69
132 #define __NR_setreuid 70
133 #define __NR_setregid 71
134 #define __NR_sigsuspend 72
135 #define __NR_sigpending 73
136 #define __NR_sethostname 74
137 #define __NR_setrlimit 75
138 #define __NR_getrlimit 76
139 #define __NR_getrusage 77
140 #define __NR_gettimeofday 78
141 #define __NR_settimeofday 79
142 #define __NR_getgroups 80
143 #define __NR_setgroups 81
144 #define __NR_select 82
145 #define __NR_symlink 83
146 #define __NR_lstat 84
147 #define __NR_readlink 85
148 #define __NR_uselib 86
149
// ���¶���ϵͳ����Ƕ��ʽ���꺯����
// ����������ϵͳ���ú꺯����type name(void)��
// %0 - eax(__res)��%1 - eax(__NR_##name)������name��ϵͳ���õ����ƣ��� __NR_ ����γ�����
// ��ϵͳ���÷��ų������Ӷ�������ϵͳ���ñ��к���ָ��Ѱַ��
// ���أ��������ֵ���ڵ���0���ظ�ֵ�������ó�����errno��������-1��
// �ں궨���У�����������Ƿ���֮�������������ľ���'##'�����ʾ�ں��滻ʱ������������
// ����������һ�����������139���ϵ�__NR_##name�����滻�˲���name��������fork��֮��
// ����ڳ����г��ֵĽ����Ƿ���__NR_fork���μ���The C Programming Language����¼A.12.3��
150 #define _syscall0(type,name) \
151 type name(void) \
152 { \
153 long __res; \
154 __asm__ volatile ("int $0x80" \ // ����ϵͳ�ж�0x80��
155 : "=a" (__res) \ // ����ֵ��eax(__res)��
156 : "0" (__NR_##name)); \ // ����Ϊϵͳ�жϵ��ú�__NR_name��
157 if (__res >= 0) \ // �������ֵ>=0����ֱ�ӷ��ظ�ֵ��
158 return (type) __res; \
159 errno = -__res; \ // �����ó����ţ�������-1��
160 return -1; \
161 }
162
// ��1��������ϵͳ���ú꺯����type name(atype a)
// %0 - eax(__res)��%1 - eax(__NR_name)��%2 - ebx(a)��
163 #define _syscall1(type,name,atype,a) \
164 type name(atype a) \
165 { \
166 long __res; \
167 __asm__ volatile ("int $0x80" \
168 : "=a" (__res) \
169 : "0" (__NR_##name),"b" ((long)(a))); \
170 if (__res >= 0) \
171 return (type) __res; \
172 errno = -__res; \
173 return -1; \
174 }
175
// ��2��������ϵͳ���ú꺯����type name(atype a, btype b)
// %0 - eax(__res)��%1 - eax(__NR_name)��%2 - ebx(a)��%3 - ecx(b)��
176 #define _syscall2(type,name,atype,a,btype,b) \
177 type name(atype a,btype b) \
178 { \
179 long __res; \
180 __asm__ volatile ("int $0x80" \
181 : "=a" (__res) \
182 : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b))); \
183 if (__res >= 0) \
184 return (type) __res; \
185 errno = -__res; \
186 return -1; \
187 }
188
// ��3��������ϵͳ���ú꺯����type name(atype a, btype b, ctype c)
// %0 - eax(__res)��%1 - eax(__NR_name)��%2 - ebx(a)��%3 - ecx(b)��%4 - edx(c)��
189 #define _syscall3(type,name,atype,a,btype,b,ctype,c) \
190 type name(atype a,btype b,ctype c) \
191 { \
192 long __res; \
193 __asm__ volatile ("int $0x80" \
194 : "=a" (__res) \
195 : "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \
196 if (__res>=0) \
197 return (type) __res; \
198 errno=-__res; \
199 return -1; \
200 }
201
202 #endif /* __LIBRARY__ */
203
204 extern int errno; // �����ţ�ȫ�ֱ�����
205
// ��Ӧ��ϵͳ���õĺ���ԭ�Ͷ��塣(��ϸ˵���μ�include/linux/sys.h )
206 int access(const char * filename, mode_t mode);
207 int acct(const char * filename);
208 int alarm(int sec);
209 int brk(void * end_data_segment);
210 void * sbrk(ptrdiff_t increment);
211 int chdir(const char * filename);
212 int chmod(const char * filename, mode_t mode);
213 int chown(const char * filename, uid_t owner, gid_t group);
214 int chroot(const char * filename);
215 int close(int fildes);
216 int creat(const char * filename, mode_t mode);
217 int dup(int fildes);
218 int execve(const char * filename, char ** argv, char ** envp);
219 int execv(const char * pathname, char ** argv);
220 int execvp(const char * file, char ** argv);
221 int execl(const char * pathname, char * arg0, ...);
222 int execlp(const char * file, char * arg0, ...);
223 int execle(const char * pathname, char * arg0, ...);
// ������ǰ�Ĺؼ���volatile���ڸ��߱�����gcc�ú������᷵�ء���������gcc��������һ
// Щ�Ĵ��룬����Ҫ����ʹ������ؼ��ֿ��Ա������ijЩ��δ��ʼ�������ģ��پ�����Ϣ��
// ��ͬ��gcc�ĺ�������˵����void do_exit(int error_code) __attribute__ ((noreturn));
224 volatile void exit(int status);
225 volatile void _exit(int status);
226 int fcntl(int fildes, int cmd, ...);
227 int fork(void);
228 int getpid(void);
229 int getuid(void);
230 int geteuid(void);
231 int getgid(void);
232 int getegid(void);
233 int ioctl(int fildes, int cmd, ...);
234 int kill(pid_t pid, int signal);
235 int link(const char * filename1, const char * filename2);
236 int lseek(int fildes, off_t offset, int origin);
237 int mknod(const char * filename, mode_t mode, dev_t dev);
238 int mount(const char * specialfile, const char * dir, int rwflag);
239 int nice(int val);
240 int open(const char * filename, int flag, ...);
241 int pause(void);
242 int pipe(int * fildes);
243 int read(int fildes, char * buf, off_t count);
244 int setpgrp(void);
245 int setpgid(pid_t pid,pid_t pgid);
246 int setuid(uid_t uid);
247 int setgid(gid_t gid);
248 void (*signal(int sig, void (*fn)(int)))(int);
249 int stat(const char * filename, struct stat * stat_buf);
250 int fstat(int fildes, struct stat * stat_buf);
251 int stime(time_t * tptr);
252 int sync(void);
253 time_t time(time_t * tloc);
254 time_t times(struct tms * tbuf);
255 int ulimit(int cmd, long limit);
256 mode_t umask(mode_t mask);
257 int umount(const char * specialfile);
258 int uname(struct utsname * name);
259 int unlink(const char * filename);
260 int ustat(dev_t dev, struct ustat * ubuf);
261 int utime(const char * filename, struct utimbuf * times);
262 pid_t waitpid(pid_t pid,int * wait_stat,int options);
263 pid_t wait(int * wait_stat);
264 int write(int fildes, const char * buf, off_t count);
265 int dup2(int oldfd, int newfd);
266 int getppid(void);
267 pid_t getpgrp(void);
268 pid_t setsid(void);
269 int sethostname(char *name, int len);
270 int setrlimit(int resource, struct rlimit *rlp);
271 int getrlimit(int resource, struct rlimit *rlp);
272 int getrusage(int who, struct rusage *rusage);
273 int gettimeofday(struct timeval *tv, struct timezone *tz);
274 int settimeofday(struct timeval *tv, struct timezone *tz);
275 int getgroups(int gidsetlen, gid_t *gidset);
276 int setgroups(int gidsetlen, gid_t *gidset);
277 int select(int width, fd_set * readfds, fd_set * writefds,
278 fd_set * exceptfds, struct timeval * timeout);
279
280 #endif
281
1 #ifndef _UTIME_H
2 #define _UTIME_H
3
4 #include <sys/types.h> /* I know - shouldn't do this, but .. */
5 /* ��֪�� - ��Ӧ��������������.. */
6 struct utimbuf {
7 time_t actime; // �ļ�����ʱ�䡣��1970.1.1:0:0:0��ʼ��������
8 time_t modtime; // �ļ���ʱ�䡣��1970.1.1:0:0:0��ʼ��������
9 };
10
// �����ļ����ʺ���ʱ�亯����
11 extern int utime(const char *filename, struct utimbuf *times);
12
13 #endif
14
//// Ӳ���˿��ֽ����������
// ������value - ������ֽڣ�port - �˿ڡ�
1 #define outb(value,port) \
2 __asm__ ("outb %%al,%%dx"::"a" (value),"d" (port))
3
4
//// Ӳ���˿��ֽ����뺯����
// ������port - �˿ڡ����ض�ȡ���ֽڡ�
5 #define inb(port) ({ \
6 unsigned char _v; \
7 __asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \
8 _v; \
9 })
10
//// ���ӳٵ�Ӳ���˿��ֽ����������ʹ��������ת������ӳ�һ�ᡣ
// ������value - ������ֽڣ�port - �˿ڡ�
11 #define outb_p(value,port) \
12 __asm__ ("outb %%al,%%dx\n" \
13 "\tjmp 1f\n" \ // ��ǰ��ת�����1��������һ����䴦����
14 "1:\tjmp 1f\n" \ // ��ǰ��ת�����1����
15 "1:"::"a" (value),"d" (port))
16
//// ���ӳٵ�Ӳ���˿��ֽ����뺯����ʹ��������ת������ӳ�һ�ᡣ
// ������port - �˿ڡ����ض�ȡ���ֽڡ�
17 #define inb_p(port) ({ \
18 unsigned char _v; \
19 __asm__ volatile ("inb %%dx,%%al\n" \
20 "\tjmp 1f\n" \ // ��ǰ��ת�����1��������һ����䴦����
21 "1:\tjmp 1f\n" \ // ��ǰ��ת�����1����
22 "1:":"=a" (_v):"d" (port)); \
23 _v; \
24 })
25
1 /*
2 * NOTE!!! memcpy(dest,src,n) assumes ds=es=normal data segment. This
3 * goes for all kernel functions (ds=es=kernel space, fs=local data,
4 * gs=null), as well as for all well-behaving user programs (ds=es=
5 * user data space). This is NOT a bug, as any user program that changes
6 * es deserves to die if it isn't careful.
7 */
/*
* ע��!!!memcpy(dest,src,n)����μĴ���ds=es=ͨ�����ݶΡ����ں���ʹ�õ�
* ���к��������ڸü��裨ds=es=�ں˿ռ䣬fs=�ֲ����ݿռ䣬gs=null��,��������
* ��Ϊ��Ӧ�ó���Ҳ��������ds=es=�û����ݿռ䣩������κ��û���������Ķ���
* es�Ĵ�������������������ϵͳ���������ɵġ�
*/
//// �ڴ�鸴�ơ���Դ��ַsrc����ʼ����n���ֽڵ�Ŀ�ĵ�ַdest����
// ������dest - ���Ƶ�Ŀ�ĵ�ַ��src - ���Ƶ�Դ��ַ��n - �����ֽ�����
// %0 - edi(Ŀ�ĵ�ַdest)��%1 - esi(Դ��ַsrc)��%2 - ecx(�ֽ���n)��
8 #define memcpy(dest,src,n) ({ \
9 void * _res = dest; \
10 __asm__ ("cld;rep;movsb" \ // ��ds:[esi]���Ƶ�es:[edi]������esi++��edi++��
// ������ecx(n)�ֽڡ�
11 ::"D" ((long)(_res)),"S" ((long)(src)),"c" ((long) (n)) \
12 :"di","si","cx"); \
13 _res; \
14 })
15
//// ��ȡfs����ָ����ַ�����ֽڡ�
// ������addr - ָ�����ڴ��ַ��
// %0 - (���ص��ֽ�_v)��%1 - (�ڴ��ַaddr)��
// ���أ������ڴ�fs:[addr]�����ֽڡ�
// ��3�ж�����һ���Ĵ�������_v���ñ�������������һ���Ĵ����У��Ա��ڸ�Ч���ʺͲ�����
1 extern inline unsigned char get_fs_byte(const char * addr)
2 {
3 unsigned register char _v;
4
5 __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr));
6 return _v;
7 }
8
//// ��ȡfs����ָ����ַ�����֡�
// ������addr - ָ�����ڴ��ַ��
// %0 - (���ص���_v)��%1 - (�ڴ��ַaddr)��
// ���أ������ڴ�fs:[addr]�����֡�
9 extern inline unsigned short get_fs_word(const unsigned short *addr)
10 {
11 unsigned short _v;
12
13 __asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
14 return _v;
15 }
16
//// ��ȡfs����ָ����ַ���ij���(4�ֽ�)��
// ������addr - ָ�����ڴ��ַ��
// %0 - (���صij���_v)��%1 - (�ڴ��ַaddr)��
// ���أ������ڴ�fs:[addr]���ij��֡�
17 extern inline unsigned long get_fs_long(const unsigned long *addr)
18 {
19 unsigned long _v;
20
21 __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
22 return _v;
23 }
24
//// ��һ�ֽڴ����fs����ָ���ڴ��ַ����
// ������val - �ֽ�ֵ��addr - �ڴ��ַ��
// %0 - �Ĵ���(�ֽ�ֵval)��%1 - (�ڴ��ַaddr)��
25 extern inline void put_fs_byte(char val,char *addr)
26 {
27 __asm__ ("movb %0,%%fs:%1"::"r" (val),"m" (*addr));
28 }
29
//// ��һ�ִ����fs����ָ���ڴ��ַ����
// ������val - ��ֵ��addr - �ڴ��ַ��
// %0 - �Ĵ���(��ֵval)��%1 - (�ڴ��ַaddr)��
30 extern inline void put_fs_word(short val,short * addr)
31 {
32 __asm__ ("movw %0,%%fs:%1"::"r" (val),"m" (*addr));
33 }
34
//// ��һ���ִ����fs����ָ���ڴ��ַ����
// ������val - ����ֵ��addr - �ڴ��ַ��
// %0 - �Ĵ���(����ֵval)��%1 - (�ڴ��ַaddr)��
35 extern inline void put_fs_long(unsigned long val,unsigned long * addr)
36 {
37 __asm__ ("movl %0,%%fs:%1"::"r" (val),"m" (*addr));
38 }
39
40 /*
41 * Someone who knows GNU asm better than I should double check the followig.
42 * It seems to work, but I don't know if I'm doing something subtly wrong.
43 * --- TYT, 11/24/91
44 * [ nothing wrong here, Linus ]
45 */
/*
* ���Ҹ���GNU������Ӧ����ϸ�������Ĵ��롣��Щ������ʹ�ã����Ҳ�֪���Ƿ�
* ����һЩС����
* --- TYT��1991��11��24��
* [ ��Щ����û�д���Linus ]
*/
46
//// ȡfs�μĴ���ֵ(ѡ���)��
// ���أ�fs�μĴ���ֵ��
47 extern inline unsigned long get_fs()
48 {
49 unsigned short _v;
50 __asm__("mov %%fs,%%ax":"=a" (_v):);
51 return _v;
52 }
53
//// ȡds�μĴ���ֵ��
// ���أ�ds�μĴ���ֵ��
54 extern inline unsigned long get_ds()
55 {
56 unsigned short _v;
57 __asm__("mov %%ds,%%ax":"=a" (_v):);
58 return _v;
59 }
60
//// ����fs�μĴ�����
// ������val - ��ֵ��ѡ�������
61 extern inline void set_fs(unsigned long val)
62 {
63 __asm__("mov %0,%%fs"::"a" ((unsigned short) val));
64 }
65
66
//// �ƶ����û�ģʽ���С�
// �ú�������iretָ��ʵ�ִ��ں�ģʽ�ƶ�����ʼ����0��ȥִ�С�
1 #define move_to_user_mode() \
2 __asm__ ("movl %%esp,%%eax\n\t" \ // �����ջָ��esp��eax�Ĵ����С�
3 "pushl $0x17\n\t" \ // ���Ƚ���ջ��ѡ���(SS)��ջ��
4 "pushl %%eax\n\t" \ // Ȼ����Ķ�ջָ��ֵ(esp)��ջ��
5 "pushfl\n\t" \ // ����־�Ĵ���(eflags)������ջ��
6 "pushl $0x0f\n\t" \ // ��Task0�����ѡ���(cs)��ջ��
7 "pushl $1f\n\t" \ // ��������1��ƫ�Ƶ�ַ(eip)��ջ��
8 "iret\n" \ // ִ���жϷ���ָ������ת��������1����
9 "1:\tmovl $0x17,%%eax\n\t" \ // ��ʱ��ʼִ������0��
10 "movw %%ax,%%ds\n\t" \ // ��ʼ���μĴ���ָ�ֲ��������ݶΡ�
11 "movw %%ax,%%es\n\t" \
12 "movw %%ax,%%fs\n\t" \
13 "movw %%ax,%%gs" \
14 :::"ax")
15
16 #define sti() __asm__ ("sti"::) // ���ж�Ƕ����꺯����
17 #define cli() __asm__ ("cli"::) // ���жϡ�
18 #define nop() __asm__ ("nop"::) // �ղ�����
19
20 #define iret() __asm__ ("iret"::) // �жϷ��ء�
21
//// �������������ꡣ
// ���ݲ����е��жϻ��쳣�������̵�ַaddr��������������type����Ȩ����Ϣdpl������λ��
// ��ַgate_addr����������������ע�⣺���桰ƫ�ơ�ֵ��������ں˴�������ݶ���˵�ģ���
// ������gate_addr -��������ַ��type -������������ֵ��dpl -��������Ȩ����addr -ƫ�Ƶ�ַ��
// %0 - (��dpl,type��ϳɵ����ͱ�־��)��%1 - (��������4�ֽڵ�ַ)��
// %2 - (��������4�ֽڵ�ַ)��%3 - edx(����ƫ�Ƶ�ַaddr)��%4 - eax(�����к��ж�ѡ���0x8)��
22 #define _set_gate(gate_addr,type,dpl,addr) \
23 __asm__ ("movw %%dx,%%ax\n\t" \ // ��ƫ�Ƶ�ַ������ѡ�����ϳ���������4�ֽ�(eax)��
24 "movw %0,%%dx\n\t" \ // �����ͱ�־����ƫ�Ƹ�����ϳ���������4�ֽ�(edx)��
25 "movl %%eax,%1\n\t" \ // �ֱ��������������ĵ�4�ֽں�4�ֽڡ�
26 "movl %%edx,%2" \
27 : \
28 : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
29 "o" (*((char *) (gate_addr))), \
30 "o" (*(4+(char *) (gate_addr))), \
31 "d" ((char *) (addr)),"a" (0x00080000))
32
//// �����ж��ź������Զ����������жϣ���
// ������n - �жϺţ�addr - �жϳ���ƫ�Ƶ�ַ��
// &idt[n]���ж������������жϺ�n��Ӧ���ƫ��ֵ���ж���������������14����Ȩ����0��
33 #define set_intr_gate(n,addr) \
34 _set_gate(&idt[n],14,0,addr)
35
//// �������������
// ������n - �жϺţ�addr - �жϳ���ƫ�Ƶ�ַ��
// &idt[n]���ж������������жϺ�n��Ӧ���ƫ��ֵ���ж���������������15����Ȩ����0��
36 #define set_trap_gate(n,addr) \
37 _set_gate(&idt[n],15,0,addr)
38
//// ����ϵͳ�����ź�����
// ����set_trap_gate()���õ�����������Ȩ��Ϊ0����������3�����set_system_gate()���õ�
// �жϴ��������ܹ������г���ִ�С����絥�����ԡ���������ͱ߽糬������������
// ������n - �жϺţ�addr - �жϳ���ƫ�Ƶ�ַ��
// &idt[n]���ж������������жϺ�n��Ӧ���ƫ��ֵ���ж���������������15����Ȩ����3��
39 #define set_system_gate(n,addr) \
40 _set_gate(&idt[n],15,3,addr)
41
//// ���ö��������������ں���û���õ�����
// ������gate_addr -��������ַ��type -��������������ֵ��dpl -��������Ȩ��ֵ��
// base - �εĻ���ַ��limit - ������
// ��μ����������ĸ�ʽ��ע�⣬���︳ֵ����Ū���ˡ�43��Ӧ���� *((gate_addr)+1)����
// 49�в��� *(gate_addr)�������ں˴�����û���õ�����꣬����Linusû�в�� :-)
42 #define _set_seg_desc(gate_addr,type,dpl,base,limit) {\
43 *(gate_addr) = ((base) & 0xff000000) | \ // ��������4�ֽڡ�
44 (((base) & 0x00ff0000)>>16) | \
45 ((limit) & 0xf0000) | \
46 ((dpl)<<13) | \
47 (0x00408000) | \
48 ((type)<<8); \
49 *((gate_addr)+1) = (((base) & 0x0000ffff)<<16) | \ // ��������4�ֽڡ�
50 ((limit) & 0x0ffff); }
51
//// ��ȫ�ֱ�����������״̬��/�ֲ�����������״̬�κ;ֲ����εij��Ⱦ������ó�104�ֽڡ�
// ������n - ��ȫ�ֱ�����������n����Ӧ�ĵ�ַ��addr - ״̬��/�ֲ��������ڴ�Ļ���ַ��
// type - �������еı�־�����ֽڡ�
// %0 - eax(��ַaddr)��%1 - (��������n�ĵ�ַ)��%2 - (��������n�ĵ�ַƫ��2��)��
// %3 - (��������n�ĵ�ַƫ��4��)��%4 - (��������n�ĵ�ַƫ��5��)��
// %5 - (��������n�ĵ�ַƫ��6��)��%6 - (��������n�ĵ�ַƫ��7��)��
52 #define _set_tssldt_desc(n,addr,type) \
53 __asm__ ("movw $104,%1\n\t" \ // ��TSS����LDT�����ȷ���������������(��0-1�ֽ�)��
54 "movw %%ax,%2\n\t" \ // ������ַ�ĵ��ַ�����������2-3�ֽڡ�
55 "rorl $16,%%eax\n\t" \ // ������ַ������ѭ������ax�У������������ִ�����
56 "movb %%al,%3\n\t" \ // ������ַ�����е��ֽ�������������4�ֽڡ�
57 "movb $" type ",%4\n\t" \ // ����־�����ֽ������������ĵ�5�ֽڡ�
58 "movb $0x00,%5\n\t" \ // �������ĵ�6�ֽ���0��
59 "movb %%ah,%6\n\t" \ // ������ַ�����и��ֽ�������������7�ֽڡ�
60 "rorl $16,%%eax" \ // ����ѭ��16���أ�eax�ָ�ԭֵ��
61 ::"a" (addr), "m" (*(n)), "m" (*(n+2)), "m" (*(n+4)), \
62 "m" (*(n+5)), "m" (*(n+6)), "m" (*(n+7)) \
63 )
64
//// ��ȫ�ֱ�����������״̬����������
// n - �Ǹ���������ָ�룻addr - �����������жεĻ���ֵַ������״̬����������������0x89��
65 #define set_tss_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x89")
//// ��ȫ�ֱ������þֲ�����������
// n - �Ǹ���������ָ�룻addr - �����������жεĻ���ֵַ���ֲ�������������������0x82��
66 #define set_ldt_desc(n,addr) _set_tssldt_desc(((char *) (n)),addr,"0x82")
67
1 #ifndef _CONFIG_H
2 #define _CONFIG_H
3
4 /*
5 * Defines for what uname() should return
6 */
/*
* ����uname()����Ӧ�÷��ص�ֵ��
*/
7 #define UTS_SYSNAME "Linux"
8 #define UTS_NODENAME "(none)" /* set by sethostname() */
9 #define UTS_RELEASE "" /* patchlevel */
10 #define UTS_VERSION "0.12"
11 #define UTS_MACHINE "i386" /* hardware type */
12
13 /* Don't touch these, unless you really know what your doing. */
/* �벻Ҫ���������涨��ֵ��������֪���Լ����ڸ�ʲô�� */
14 #define DEF_INITSEG 0x9000 // �������������ƶ����Ķ�ֵ��
15 #define DEF_SYSSEG 0x1000 // �������������ϵͳģ����ص��ڴ�Ķ�ֵ��
16 #define DEF_SETUPSEG 0x9020 // setup���������ڴ��λ�á�
17 #define DEF_SYSSIZE 0x3000 // �ں�ϵͳģ��Ĭ����������16�ֽ�=1�ڣ���
18
19 /*
20 * The root-device is no longer hard-coded. You can change the default
21 * root-device by changing the line ROOT_DEV = XXX in boot/bootsect.s
22 */
/*
* ���ļ�ϵͳ�豸�Ѳ�����Ӳ������ˡ�ͨ����boot/bootsect.s�ļ�����
* ROOT_DEV = XXX������Ըı���豸��Ĭ������ֵ��
*/
23
24 /*
25 * The keyboard is now defined in kernel/chr_dev/keyboard.S
26 */
/*
* ���ڼ������ͱ�����kernel/chr_dev/keyboard.S�����ж��塣
*/
27
28 /*
29 * Normally, Linux can get the drive parameters from the BIOS at
30 * startup, but if this for some unfathomable reason fails, you'd
31 * be left stranded. For this case, you can define HD_TYPE, which
32 * contains all necessary info on your harddisk.
33 *
34 * The HD_TYPE macro should look like this:
35 *
36 * #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl}
37 *
38 * In case of two harddisks, the info should be sepatated by
39 * commas:
40 *
41 * #define HD_TYPE { h,s,c,wpcom,lz,ctl },{ h,s,c,wpcom,lz,ctl }
42 */
/*
* ͨ����Linux�ܹ�������ʱ��BIOS�л�ȡ�������²���������������δ֪ԭ��
* ��û�еõ���Щ����ʱ����ʹ���������ߡ������������������Զ���HD_TYPE��
* ���а���Ӳ�̵�������Ϣ��
*
* HD_TYPE��Ӧ����������������ʽ��
*
* #define HD_TYPE { head, sect, cyl, wpcom, lzone, ctl}
*
* ����������Ӳ�̵������������Ϣ���ö��ŷֿ���
*
* #define HD_TYPE { h,s,c,wpcom,lz,ctl }, {h,s,c,wpcom,lz,ctl }
*/
43 /*
44 This is an example, two drives, first is type 2, second is type 3:
45
46 #define HD_TYPE { 4,17,615,300,615,8 }, { 6,17,615,300,615,0 }
47
48 NOTE: ctl is 0 for all drives with heads<=8, and ctl=8 for drives
49 with more than 8 heads.
50
51 If you want the BIOS to tell what kind of drive you have, just
52 leave HD_TYPE undefined. This is the normal thing to do.
53 */
/*
* ������һ�����ӣ�����Ӳ�̣���1��������2����2��������3��
*
* #define HD_TYPE { 4,17,615,300,615,8 }, {6,17,615,300,615,0 }
*
* ע�⣺��Ӧ����Ӳ�̣������ͷ��<=8����ctl����0������ͷ������8����
* ��ctl=8��
*
* ���������BIOS����Ӳ�̵����ͣ���ôֻ�費����HD_TYPE������Ĭ�ϲ�����
*/
54
55 #endif
56
1 /*
2 * This file contains some defines for the floppy disk controller.
3 * Various sources. Mostly "IBM Microcomputers: A Programmers
4 * Handbook", Sanches and Canton.
5 */
/*
* ���ļ��к���һЩ���̿�������һЩ���塣��Щ��Ϣ�жദ��Դ�������ȡ��Sanches��Canton
* ������"IBM�ͼ����������Ա�ֲ�"һ�顣
*/
6 #ifndef _FDREG_H // �ö��������ų��������ظ�������ͷ�ļ���
7 #define _FDREG_H
8
// һЩ�������ͺ�����ԭ��˵����
9 extern int ticks_to_floppy_on(unsigned int nr);
10 extern void floppy_on(unsigned int nr);
11 extern void floppy_off(unsigned int nr);
12 extern void floppy_select(unsigned int nr);
13 extern void floppy_deselect(unsigned int nr);
14
// �������й����̿�����һЩ�˿ںͷ��ŵĶ��塣
15 /* Fd controller regs. S&C, about page 340 */
/* ���̿�����(FDC)�Ĵ����˿ڡ�ժ��S&C����Լ340ҳ */
16 #define FD_STATUS 0x3f4 // ��״̬�Ĵ����˿ڡ�
17 #define FD_DATA 0x3f5 // ���ݶ˿ڡ�
18 #define FD_DOR 0x3f2 /* Digital Output Register */
// ��������Ĵ�����Ҳ��Ϊ���ֿ��ƼĴ�������
19 #define FD_DIR 0x3f7 /* Digital Input Register (read) */
// ��������Ĵ�����
20 #define FD_DCR 0x3f7 /* Diskette Control Register (write)*/
// ���ݴ����ʿ��ƼĴ�����
21
22 /* Bits of main status register */
/* ��״̬�Ĵ���������λ�ĺ��� */
23 #define STATUS_BUSYMASK 0x0F /* drive busy mask */
// ������æλ��ÿλ��Ӧһ������������
24 #define STATUS_BUSY 0x10 /* FDC busy */
// ���̿�����æ��
25 #define STATUS_DMA 0x20 /* 0- DMA mode */
// 0 - ΪDMA���ݴ���ģʽ��1 - Ϊ��DMAģʽ��
26 #define STATUS_DIR 0x40 /* 0- cpu->fdc */
// ���䷽��0 - CPU �� fdc��1 - �෴��
27 #define STATUS_READY 0x80 /* Data reg ready */
// ���ݼĴ�������λ��
28
29 /* Bits of FD_ST0 */
/*״̬�ֽ�0��ST0��������λ�ĺ��� */
30 #define ST0_DS 0x03 /* drive select mask */
// ������ѡ��ţ������ж�ʱ�������ţ���
31 #define ST0_HA 0x04 /* Head (Address) */
// ��ͷ�š�
32 #define ST0_NR 0x08 /* Not Ready */
// ����������δ���á�
33 #define ST0_ECE 0x10 /* Equipment chech error */
// �豸����������ŵ�У��������
34 #define ST0_SE 0x20 /* Seek end */
// Ѱ��������У������ִ�н�����
35 #define ST0_INTR 0xC0 /* Interrupt code mask */
// �жϴ���λ���ж�ԭ��00 - ��������������
// 01 - �����쳣������10 - ������Ч��11 - FDD����״̬�ı䡣
36
37 /* Bits of FD_ST1 */
/*״̬�ֽ�1��ST1��������λ�ĺ��� */
38 #define ST1_MAM 0x01 /* Missing Address Mark */
// δ�ҵ���ַ��־(ID AM)��
39 #define ST1_WP 0x02 /* Write Protect */
// �����
40 #define ST1_ND 0x04 /* No Data - unreadable */
// δ�ҵ�ָ����������
41 #define ST1_OR 0x10 /* OverRun */
// ���ݴ��䳬ʱ��DMA���������ϣ���
42 #define ST1_CRC 0x20 /* CRC error in data or addr */
// CRC���������
43 #define ST1_EOC 0x80 /* End Of Cylinder */
// ���ʳ���һ���ŵ��ϵ���������š�
44
45 /* Bits of FD_ST2 */
/*״̬�ֽ�2��ST2��������λ�ĺ��� */
46 #define ST2_MAM 0x01 /* Missing Addess Mark (again) */
// δ�ҵ����ݵ�ַ��־��
47 #define ST2_BC 0x02 /* Bad Cylinder */
// �ŵ�����
48 #define ST2_SNS 0x04 /* Scan Not Satisfied */
// ������ɨ�裩���������㡣
49 #define ST2_SEH 0x08 /* Scan Equal Hit */
// �����������㡣
50 #define ST2_WC 0x10 /* Wrong Cylinder */
// �ŵ������棩�Ų�����
51 #define ST2_CRC 0x20 /* CRC error in data field */
// ���ݳ�CRCУ�����
52 #define ST2_CM 0x40 /* Control Mark = deleted */
// ����������ɾ����־��
53
54 /* Bits of FD_ST3 */
/*״̬�ֽ�3��ST3��������λ�ĺ��� */
55 #define ST3_HA 0x04 /* Head (Address) */
// ��ͷ�š�
56 #define ST3_TZ 0x10 /* Track Zero signal (1=track 0) */
// ��ŵ��źš�
57 #define ST3_WP 0x40 /* Write Protect */
// �����
58
59 /* Values for FD_COMMAND */
/* ���������� */
60 #define FD_RECALIBRATE 0x07 /* move to track 0 */
// ����У��(��ͷ�˵���ŵ�)��
61 #define FD_SEEK 0x0F /* seek track */
// ��ͷѰ����
62 #define FD_READ 0xE6 /* read with MT, MFM, SKip deleted */
// �����ݣ�MT��ŵ�������MFM��ʽ������ɾ�����ݣ���
63 #define FD_WRITE 0xC5 /* write with MT, MFM */
// д���ݣ�MT��MFM����
64 #define FD_SENSEI 0x08 /* Sense Interrupt Status */
// ����ж�״̬��
65 #define FD_SPECIFY 0x03 /* specify HUT etc */
// �趨�������������������ʡ���ͷж��ʱ��ȣ���
66
67 /* DMA commands */
/* DMA ���� */
68 #define DMA_READ 0x46 // DMA���̣�DMA��ʽ�֣���DMA�˿�12��11����
69 #define DMA_WRITE 0x4A // DMAд�̣�DMA��ʽ�֡�
70
71 #endif
72
1 /*
2 * This file has definitions for some important file table
3 * structures etc.
4 */
/*
* ���ļ�����ijЩ��Ҫ�ļ����ṹ�Ķ���ȡ�
*/
5
6 #ifndef _FS_H
7 #define _FS_H
8
9 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
10
11 /* devices are as follows: (same as minix, so we can use the minix
12 * file system. These are major numbers.)
13 *
14 * 0 - unused (nodev)
15 * 1 - /dev/mem
16 * 2 - /dev/fd
17 * 3 - /dev/hd
18 * 4 - /dev/ttyx
19 * 5 - /dev/tty
20 * 6 - /dev/lp
21 * 7 - unnamed pipes
22 */
/*
* ϵͳ�������豸���£�����minixϵͳ��һ�����������ǿ���ʹ��minix��
* �ļ�ϵͳ��������Щ�����豸�š���
*
* 0 - û���õ���nodev��
* 1 - /dev/mem �ڴ��豸��
* 2 - /dev/fd �����豸��
* 3 - /dev/hd Ӳ���豸��
* 4 - /dev/ttyx tty�����ն��豸��
* 5 - /dev/tty tty�ն��豸��
* 6 - /dev/lp ��ӡ�豸��
* 7 - unnamed pipes û�������Ĺܵ���
*/
23
24 #define IS_SEEKABLE(x) ((x)>=1 && (x)<=3) // �ж��豸�Ƿ��ǿ���Ѱ�Ҷ�λ�ġ�
25
26 #define READ 0
27 #define WRITE 1
28 #define READA 2 /* read-ahead - don't pause */
29 #define WRITEA 3 /* "write-ahead" - silly, but somewhat useful */
30
31 void buffer_init(long buffer_end); // ���ٻ�������ʼ��������
32
33 #define MAJOR(a) (((unsigned)(a))>>8) // ȡ���ֽڣ����豸�ţ���
34 #define MINOR(a) ((a)&0xff) // ȡ���ֽڣ����豸�ţ���
35
36 #define NAME_LEN 14 // ���ֳ���ֵ��
37 #define ROOT_INO 1 // ��i�ڵ㡣
38
39 #define I_MAP_SLOTS 8 // i�ڵ�λͼ������
40 #define Z_MAP_SLOTS 8 // ���飨���ο飩λͼ������
41 #define SUPER_MAGIC 0x137F // �ļ�ϵͳħ����
42
43 #define NR_OPEN 20 // �������������
44 #define NR_INODE 32 // ϵͳͬʱ���ʹ��I�ڵ������
45 #define NR_FILE 64 // ϵͳ����ļ��������ļ�������������
46 #define NR_SUPER 8 // ϵͳ���������������������������������
47 #define NR_HASH 307 // ������Hash����������ֵ��
48 #define NR_BUFFERS nr_buffers // ϵͳ����������������ʼ�����ٸı䡣
49 #define BLOCK_SIZE 1024 // ���ݿ鳤�ȣ��ֽ�ֵ����
50 #define BLOCK_SIZE_BITS 10 // ���ݿ鳤����ռ����λ����
51 #ifndef NULL
52 #define NULL ((void *) 0)
53 #endif
54
// ÿ������ɴ�ŵ�i�ڵ�����
55 #define INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct d_inode)))
// ÿ������ɴ�ŵ�Ŀ¼������
56 #define DIR_ENTRIES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct dir_entry)))
57
// �ܵ�ͷ���ܵ�β���ܵ���С���ܵ��գ����ܵ��������ܵ�ͷָ�������
58 #define PIPE_READ_WAIT(inode) ((inode).i_wait)
59 #define PIPE_WRITE_WAIT(inode) ((inode).i_wait2)
60 #define PIPE_HEAD(inode) ((inode).i_zone[0])
61 #define PIPE_TAIL(inode) ((inode).i_zone[1])
62 #define PIPE_SIZE(inode) ((PIPE_HEAD(inode)-PIPE_TAIL(inode))&(PAGE_SIZE-1))
63 #define PIPE_EMPTY(inode) (PIPE_HEAD(inode)==PIPE_TAIL(inode))
64 #define PIPE_FULL(inode) (PIPE_SIZE(inode)==(PAGE_SIZE-1))
65
66 #define NIL_FILP ((struct file *)0) // ���ļ��ṹָ�롣
67 #define SEL_IN 1
68 #define SEL_OUT 2
69 #define SEL_EX 4
70
71 typedef char buffer_block[BLOCK_SIZE]; // �黺������
72
// �����ͷ���ݽṹ������Ϊ��Ҫ��������
// �ڳ����г���bh����ʾbuffer_head���͵���д��
73 struct buffer_head {
74 char * b_data; /* pointer to data block (1024 bytes) */ //ָ�롣
75 unsigned long b_blocknr; /* block number */ // ��š�
76 unsigned short b_dev; /* device (0 = free) */ // ����Դ���豸�š�
77 unsigned char b_uptodate; // ���±�־����ʾ�����Ƿ��Ѹ��¡�
78 unsigned char b_dirt; /* 0-clean,1-dirty */ //�ı�־:0δ��,1����.
79 unsigned char b_count; /* users using this block */ // ʹ�õ��û�����
80 unsigned char b_lock; /* 0 - ok, 1 -locked */ // �������Ƿ�������
81 struct task_struct * b_wait; // ָ��ȴ��û���������������
82 struct buffer_head * b_prev; // hash������ǰһ�飨���ĸ�ָ�����ڻ������Ĺ�������
83 struct buffer_head * b_next; // hash��������һ�顣
84 struct buffer_head * b_prev_free; // ���б���ǰһ�顣
85 struct buffer_head * b_next_free; // ���б�����һ�顣
86 };
87
// �����ϵ������ڵ�(i�ڵ�)���ݽṹ��
88 struct d_inode {
89 unsigned short i_mode; // �ļ����ͺ�����(rwxλ)��
90 unsigned short i_uid; // �û�id���ļ�ӵ���߱�ʶ������
91 unsigned long i_size; // �ļ���С���ֽ�������
92 unsigned long i_time; // ��ʱ�䣨��1970.1.1:0�����룩��
93 unsigned char i_gid; // ��id(�ļ�ӵ�������ڵ���)��
94 unsigned char i_nlinks; // �����������ٸ��ļ�Ŀ¼��ָ���i�ڵ㣩��
95 unsigned short i_zone[9]; // ֱ��(0-6)�����(7)��˫�ؼ��(8)����š�
// zone��������˼����������Σ������顣
96 };
97
// �������ڴ��е�i�ڵ�ṹ��ǰ7����d_inode��ȫһ����
98 struct m_inode {
99 unsigned short i_mode; // �ļ����ͺ�����(rwxλ)��
100 unsigned short i_uid; // �û�id���ļ�ӵ���߱�ʶ������
101 unsigned long i_size; // �ļ���С���ֽ�������
102 unsigned long i_mtime; // ��ʱ�䣨��1970.1.1:0�����룩��
103 unsigned char i_gid; // ��id(�ļ�ӵ�������ڵ���)��
104 unsigned char i_nlinks; // �ļ�Ŀ¼����������
105 unsigned short i_zone[9]; // ֱ��(0-6)�����(7)��˫�ؼ��(8)����š�
106 /* these are in memory also */
107 struct task_struct * i_wait; // �ȴ���i�ڵ�Ľ��̡�
108 struct task_struct * i_wait2; /* for pipes */
109 unsigned long i_atime; // ������ʱ�䡣
110 unsigned long i_ctime; // i�ڵ�������ʱ�䡣
111 unsigned short i_dev; // i�ڵ����ڵ��豸�š�
112 unsigned short i_num; // i�ڵ�š�
113 unsigned short i_count; // i�ڵ㱻ʹ�õĴ�����0��ʾ��i�ڵ���С�
114 unsigned char i_lock; // ������־��
115 unsigned char i_dirt; // ����(��)��־��
116 unsigned char i_pipe; // �ܵ���־��
117 unsigned char i_mount; // ��װ��־��
118 unsigned char i_seek; // ��Ѱ��־(lseekʱ)��
119 unsigned char i_update; // ���±�־��
120 };
121
// �ļ��ṹ���������ļ������i�ڵ�֮�佨����ϵ��
122 struct file {
123 unsigned short f_mode; // �ļ�����ģʽ��RWλ��
124 unsigned short f_flags; // �ļ��Ϳ��Ƶı�־��
125 unsigned short f_count; // ��Ӧ�ļ����ü���ֵ��
126 struct m_inode * f_inode; // ָ���Ӧi�ڵ㡣
127 off_t f_pos; // �ļ�λ�ã���дƫ��ֵ����
128 };
129
// �ڴ��д��̳�����ṹ��
130 struct super_block {
131 unsigned short s_ninodes; // �ڵ�����
132 unsigned short s_nzones; // ��������
133 unsigned short s_imap_blocks; // i�ڵ�λͼ��ռ�õ����ݿ�����
134 unsigned short s_zmap_blocks; // ����λͼ��ռ�õ����ݿ�����
135 unsigned short s_firstdatazone; // ��һ����������š�
136 unsigned short s_log_zone_size; // log(���ݿ���/����)������2Ϊ�ף���
137 unsigned long s_max_size; // �ļ���ȡ�
138 unsigned short s_magic; // �ļ�ϵͳħ����
139 /* These are only in memory */
140 struct buffer_head * s_imap[8]; // i�ڵ�λͼ�����ָ������(ռ��8�飬�ɱ�ʾ64M)��
141 struct buffer_head * s_zmap[8]; // ����λͼ�����ָ�����飨ռ��8�飩��
142 unsigned short s_dev; // ���������ڵ��豸�š�
143 struct m_inode * s_isup; // ����װ���ļ�ϵͳ��Ŀ¼��i�ڵ㡣(isup-super i)
144 struct m_inode * s_imount; // ����װ����i�ڵ㡣
145 unsigned long s_time; // ��ʱ�䡣
146 struct task_struct * s_wait; // �ȴ��ó�����Ľ��̡�
147 unsigned char s_lock; // ��������־��
148 unsigned char s_rd_only; // ֻ����־��
149 unsigned char s_dirt; // ����(��)��־��
150 };
151
// �����ϳ�����ṹ������125-132����ȫһ����
152 struct d_super_block {
153 unsigned short s_ninodes; // �ڵ�����
154 unsigned short s_nzones; // ��������
155 unsigned short s_imap_blocks; // i�ڵ�λͼ��ռ�õ����ݿ�����
156 unsigned short s_zmap_blocks; // ����λͼ��ռ�õ����ݿ�����
157 unsigned short s_firstdatazone; // ��һ���������顣
158 unsigned short s_log_zone_size; // log(���ݿ���/����)������2Ϊ�ף���
159 unsigned long s_max_size; // �ļ���ȡ�
160 unsigned short s_magic; // �ļ�ϵͳħ����
161 };
162
// �ļ�Ŀ¼��ṹ��
163 struct dir_entry {
164 unsigned short inode; // i�ڵ�š�
165 char name[NAME_LEN]; // ���������NAME_LEN=14��
166 };
167
168 extern struct m_inode inode_table[NR_INODE]; // ����i�ڵ�����飨32���
169 extern struct file file_table[NR_FILE]; // �ļ������飨64���
170 extern struct super_block super_block[NR_SUPER]; // ���������飨8���
171 extern struct buffer_head * start_buffer; // ��������ʼ�ڴ�λ�á�
172 extern int nr_buffers; // ���������
173
//// ���̲�������ԭ�͡�
// ����������������Ƿ�ı䡣
174 extern void check_disk_change(int dev);
// ���ָ�����������̸��������������̸�������1������0��
175 extern int floppy_change(unsigned int nr);
// ��������ָ������������ȴ���ʱ�䣨���õȴ���ʱ������
176 extern int ticks_to_floppy_on(unsigned int dev);
// ����ָ����������
177 extern void floppy_on(unsigned int dev);
// �ر�ָ����������������
178 extern void floppy_off(unsigned int dev);
//// �������ļ�ϵͳ���������õĺ���ԭ�͡�
// ��i�ڵ�ָ�����ļ���Ϊ0��
179 extern void truncate(struct m_inode * inode);
// ˢ��i�ڵ���Ϣ��
180 extern void sync_inodes(void);
// �ȴ�ָ����i�ڵ㡣
181 extern void wait_on(struct m_inode * inode);
// ����(���Σ����̿�)λͼ������ȡ���ݿ�block���豸�϶�Ӧ������š�
182 extern int bmap(struct m_inode * inode,int block);
// �������ݿ�block���豸�϶�Ӧ�����飬���������豸�ϵ�����š�
183 extern int create_block(struct m_inode * inode,int block);
// ��ȡָ��·������i�ڵ�š�
184 extern struct m_inode * namei(const char * pathname);
// ȡָ��·������i�ڵ㣬������������ӡ�
185 extern struct m_inode * lnamei(const char * pathname);
// ����·����Ϊ���ļ�����������
186 extern int open_namei(const char * pathname, int flag, int mode,
187 struct m_inode ** res_inode);
// �ͷ�һ��i�ڵ�(��д���豸)��
188 extern void iput(struct m_inode * inode);
// ���豸��ȡָ���ڵ�ŵ�һ��i�ڵ㡣
189 extern struct m_inode * iget(int dev,int nr);
// ��i�ڵ��(inode_table)�л�ȡһ������i�ڵ��
190 extern struct m_inode * get_empty_inode(void);
// ��ȡ������һ���ܵ��ڵ㡣����Ϊi�ڵ�ָ�루�����NULL��ʧ�ܣ���
191 extern struct m_inode * get_pipe_inode(void);
// �ڹ�ϣ���в���ָ�������ݿ顣�����ҵ���Ļ���ͷָ�롣
192 extern struct buffer_head * get_hash_table(int dev, int block);
// ���豸��ȡָ���飨���Ȼ���hash���в��ң���
193 extern struct buffer_head * getblk(int dev, int block);
// ��/д���ݿ顣
194 extern void ll_rw_block(int rw, struct buffer_head * bh);
// ��/д����ҳ�棬��ÿ��4�����ݿ顣
195 extern void ll_rw_page(int rw, int dev, int nr, char * buffer);
// �ͷ�ָ������顣
196 extern void brelse(struct buffer_head * buf);
// ��ȡָ�������ݿ顣
197 extern struct buffer_head * bread(int dev,int block);
// ��4�黺������ָ����ַ���ڴ��С�
198 extern void bread_page(unsigned long addr,int dev,int b[4]);
// ��ȡͷһ��ָ�������ݿ飬����Ǻ�����Ҫ���Ŀ顣
199 extern struct buffer_head * breada(int dev,int block,...);
// ���豸dev����һ�����̿飨���Σ����飩�����������
200 extern int new_block(int dev);
// �ͷ��豸�������е�����(���Σ����̿�)block����λָ������block������λͼ����λ��
201 extern void free_block(int dev, int block);
// Ϊ�豸dev����һ����i�ڵ㣬����i�ڵ�š�
202 extern struct m_inode * new_inode(int dev);
// �ͷ�һ��i�ڵ㣨ɾ���ļ�ʱ����
203 extern void free_inode(struct m_inode * inode);
// ˢ��ָ���豸��������
204 extern int sync_dev(int dev);
// ��ȡָ���豸�ij����顣
205 extern struct super_block * get_super(int dev);
206 extern int ROOT_DEV;
207
// ��װ���ļ�ϵͳ��
208 extern void mount_root(void);
209
210 #endif
211
1 /*
2 * This file contains some defines for the AT-hd-controller.
3 * Various sources. Check out some definitions (see comments with
4 * a ques).
5 */
/*
* ���ļ�����һЩATӲ�̿������Ķ��塣���Ը������ϡ����֤ijЩ
* ���壨�����ʺŵ�ע�ͣ���
*/
6 #ifndef _HDREG_H
7 #define _HDREG_H
8
9 /* Hd controller regs. Ref: IBM AT Bios-listing */
/* Ӳ�̿������Ĵ����˿ڡ��μ���IBM AT Bios���� */
10 #define HD_DATA 0x1f0 /* _CTL when writing */
11 #define HD_ERROR 0x1f1 /* see err-bits */
12 #define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
13 #define HD_SECTOR 0x1f3 /* starting sector */
14 #define HD_LCYL 0x1f4 /* starting cylinder */
15 #define HD_HCYL 0x1f5 /* high byte of starting cyl */
16 #define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
17 #define HD_STATUS 0x1f7 /* see status-bits */
18 #define HD_PRECOMP HD_ERROR /* same io address, read=error, write=precomp */
19 #define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
20
21 #define HD_CMD 0x3f6 // ���ƼĴ����˿ڡ�
22
23 /* Bits of HD_STATUS */
/* Ӳ��״̬�Ĵ�����λ�Ķ���(HD_STATUS) */
24 #define ERR_STAT 0x01 // ����ִ�д���
25 #define INDEX_STAT 0x02 // �յ�������
26 #define ECC_STAT 0x04 /* Corrected error */ // ECC�����
27 #define DRQ_STAT 0x08 // �������
28 #define SEEK_STAT 0x10 // Ѱ��������
29 #define WRERR_STAT 0x20 // ���������ϡ�
30 #define READY_STAT 0x40 // �����������������
31 #define BUSY_STAT 0x80 // ��������
32
33 /* Values for HD_COMMAND */
/* Ӳ������ֵ��HD_CMD�� */
34 #define WIN_RESTORE 0x10 // ����������У������������λ����
35 #define WIN_READ 0x20 // ��������
36 #define WIN_WRITE 0x30 // �����
37 #define WIN_VERIFY 0x40 // �������顣
38 #define WIN_FORMAT 0x50 // ��ʽ���ŵ���
39 #define WIN_INIT 0x60 // ��������ʼ����
40 #define WIN_SEEK 0x70 // Ѱ����
41 #define WIN_DIAGNOSE 0x90 // ��������ϡ�
42 #define WIN_SPECIFY 0x91 // ����������������
43
44 /* Bits for HD_ERROR */
/* ����Ĵ���������λ�ĺ��壨HD_ERROR�� */
// ִ�п������������ʱ��������������ʱ�IJ�ͬ������ֱ��г���
// ==================================================
// �������ʱ ��������ʱ
// --------------------------------------------------
// 0x01 ���� ���ݱ�־��ʧ
// 0x02 ���������� �ŵ�0��
// 0x03 ������������
// 0x04 ECC������ �������
// 0x05 ���ƴ�������
// 0x10 IDδ�ҵ�
// 0x40 ECC����
// 0x80 ������
//---------------------------------------------------
45 #define MARK_ERR 0x01 /* Bad address mark ? */
46 #define TRK0_ERR 0x02 /* couldn't find track 0 */
47 #define ABRT_ERR 0x04 /* ? */
48 #define ID_ERR 0x10 /* ? */
49 #define ECC_ERR 0x40 /* ? */
50 #define BBD_ERR 0x80 /* ? */
51
// Ӳ�̷������ṹ���μ������б�����Ϣ��
52 struct partition {
53 unsigned char boot_ind; /* 0x80 - active (unused) */
54 unsigned char head; /* ? */
55 unsigned char sector; /* ? */
56 unsigned char cyl; /* ? */
57 unsigned char sys_ind; /* ? */
58 unsigned char end_head; /* ? */
59 unsigned char end_sector; /* ? */
60 unsigned char end_cyl; /* ? */
61 unsigned int start_sect; /* starting sector counting from 0 */
62 unsigned int nr_sects; /* nr of sectors in partition */
63 };
64
65 #endif
66
1 #ifndef _HEAD_H
2 #define _HEAD_H
3
4 typedef struct desc_struct { // �����˶������������ݽṹ���ýṹ��˵��ÿ������
5 unsigned long a,b; // ������8���ֽڹ��ɣ�ÿ��������������256�
6 } desc_table[256];
7
8 extern unsigned long pg_dir[1024]; // �ڴ�ҳĿ¼���顣ÿ��Ŀ¼��Ϊ4�ֽڡ���������ַ0��ʼ��
9 extern desc_table idt,gdt; // �ж�����������ȫ������������
10
11 #define GDT_NUL 0 // ȫ�����������ĵ�0����á�
12 #define GDT_CODE 1 // ��1����ں˴�����������
13 #define GDT_DATA 2 // ��2����ں����ݶ��������
14 #define GDT_TMP 3 // ��3�ϵͳ����������Linuxû��ʹ�á�
15
16 #define LDT_NUL 0 // ÿ���ֲ����������ĵ�0����á�
17 #define LDT_CODE 1 // ��1����û����������������
18 #define LDT_DATA 2 // ��2����û��������ݶ��������
19
20 #endif
21
1 /*
2 * 'kernel.h' contains some often-used function prototypes etc
3 */
/*
* 'kernel.h'������һЩ���ú�����ԭ�͵ȡ�
*/
// ��֤������ַ��ʼ���ڴ���Ƿ��ޡ������������ڴ档( kernel/fork.c, 24 )��
4 void verify_area(void * addr,int count);
// ��ʾ�ں˳�����Ϣ��Ȼ�������ѭ����( kernel/panic.c, 16 )��
// ������ǰ�Ĺؼ���volatile���ڸ��߱�����gcc�ú������᷵�ء���������gcc��������
// һЩ�Ĵ��룬����Ҫ����ʹ������ؼ��ֿ��Ա������ijδ��ʼ�������ļپ�����Ϣ��
5 volatile void panic(const char * str);
// �����˳��������� kernel/exit.c��262 ����
6 volatile void do_exit(long error_code);
// ����ӡ����ʾ��������( init/main.c, 151)��
7 int printf(const char * fmt, ...);
// �ں�ר�õĴ�ӡ��Ϣ������������printf()��ͬ��( kernel/printk.c, 21 )��
8 int printk(const char * fmt, ...);
// ����̨��ʾ�������� kernel/chr_drv/console.c��995����
9 void console_print(const char * str);
// ��tty��дָ�����ȵ��ַ�����( kernel/chr_drv/tty_io.c, 290 )��
10 int tty_write(unsigned ch,char * buf,int count);
// ͨ���ں��ڴ���亯����( lib/malloc.c, 117)��
11 void * malloc(unsigned int size);
// �ͷ�ָ������ռ�õ��ڴ档( lib/malloc.c, 182)��
12 void free_s(void * obj, int size);
// Ӳ�̴�����ʱ����kernel/blk_drv/hd.c��318����
13 extern void hd_times_out(void);
// ֹͣ��������kernel/chr_drv/console.c��944����
14 extern void sysbeepstop(void);
// ������������kernel/chr_drv/console.c��981����
15 extern void blank_screen(void);
// �ָ�����������Ļ����kernel/chr_drv/console.c��988����
16 extern void unblank_screen(void);
17
18 extern int beepcount; // ����ʱ����઼�����kernel/chr_drv/console.c��988����
19 extern int hd_timeout; // Ӳ�̳�ʱ�δ�ֵ��kernel/blk_drv/blk.h����
20 extern int blankinterval; // �趨����Ļ�������ʱ�䡣
21 extern int blankcount; // ����ʱ�������kernel/chr_drv/console.c��138��139����
22
23 #define free(x) free_s((x), 0)
24
25 /*
26 * This is defined as a macro, but at some point this might become a
27 * real subroutine that sets a flag if it returns true (to do
28 * BSD-style accounting where the process is flagged if it uses root
29 * privs). The implication of this is that you should do normal
30 * permissions checks first, and check suser() last.
31 */
/*
* ���溯�����Ժ����ʽ����ģ�������ij�������������Գ�Ϊһ���������ӳ���
* ���������trueʱ�������ñ�־�����ʹ��root�û�Ȩ�Ľ��������˱�־������
* ��ִ��BSD��ʽ�ļ��ʴ�����������ζ����Ӧ������ִ�г���Ȩ��飬�����
* ���suser()��
*/
32 #define suser() (current->euid == 0) // ����Ƿ��dz����û���
33
1 /*
2 * linux/include/linux/math_emu.h
3 *
4 * (C) 1991 Linus Torvalds
5 */
6 #ifndef _LINUX_MATH_EMU_H
7 #define _LINUX_MATH_EMU_H
8
9 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0 �����ݣ�
// ����һЩ�й��������������úͻ�ȡ��Ƕ��ʽ��ຯ������䡣
10
// CPU�����쳣�ж�int 7ʱ��ջ�зֲ������ݹ��ɵĽṹ����ϵͳ����ʱ�ں�ջ�����ݷֲ����ơ�
11 struct info {
12 long ___math_ret; // math_emulate()�����ߣ�int7�����ص�ַ��
13 long ___orig_eip; // ��ʱ����ԭEIP �ĵط���
14 long ___edi; // �쳣�ж�int7 ����������ջ�ļĴ�����
15 long ___esi;
16 long ___ebp;
17 long ___sys_call_ret; // �ж�7 ����ʱ��ȥִ��ϵͳ���õķ��ش������롣
18 long ___eax; // ���²��֣�18--30 �У���ϵͳ����ʱջ�нṹ��ͬ��
19 long ___ebx;
20 long ___ecx;
21 long ___edx;
22 long ___orig_eax; // �粻��ϵͳ���ö��������ж�ʱ����ֵΪ-1��
23 long ___fs;
24 long ___es;
25 long ___ds;
26 long ___eip; // 26 -- 30 �� ��CPU �Զ���ջ��
27 long ___cs;
28 long ___eflags;
29 long ___esp;
30 long ___ss;
31 };
32
// Ϊ��������info�ṹ�и��ֶΣ�ջ�����ݣ��������һЩ������
33 #define EAX (info->___eax)
34 #define EBX (info->___ebx)
35 #define ECX (info->___ecx)
36 #define EDX (info->___edx)
37 #define ESI (info->___esi)
38 #define EDI (info->___edi)
39 #define EBP (info->___ebp)
40 #define ESP (info->___esp)
41 #define EIP (info->___eip)
42 #define ORIG_EIP (info->___orig_eip)
43 #define EFLAGS (info->___eflags)
44 #define DS (*(unsigned short *) &(info->___ds))
45 #define ES (*(unsigned short *) &(info->___es))
46 #define FS (*(unsigned short *) &(info->___fs))
47 #define CS (*(unsigned short *) &(info->___cs))
48 #define SS (*(unsigned short *) &(info->___ss))
49
// ��ֹ��ѧЭ�����������������math_emulation.c������ʵ��(L488�У���
// ����52-53���Ϻ궨���ʵ�������ǰ�__math_abort���¶���Ϊһ�����᷵�صĺ���
// ������ǰ�������volatile�����ú��ǰ���֣�
// (volatile void (*)(struct info *,unsigned int))
// �Ǻ������Ͷ��壬��������ָ�� __math_abort�����Ķ��塣����������Ӧ�IJ�����
// �ؼ���volatile ���ں�����ǰ�����κ�����������֪ͨgcc �������ú������᷵��,
// ����gcc ��������һЩ�Ĵ��롣��ϸ˵����μ���3�� $3.3.2�����ݡ�
// �������ĺ궨�壬����ҪĿ�ľ�������__math_abort����������������ͨ�з��غ�����
// �ֿ�����ʹ�ú궨��math_abort() ʱ���������صĺ�����
50 void __math_abort(struct info *, unsigned int);
51
52 #define math_abort(x,y) \
53 (((volatile void (*)(struct info *,unsigned int)) __math_abort)((x),(y)))
54
55 /*
56 * Gcc forces this stupid alignment problem: I want to use only two longs
57 * for the temporary real 64-bit mantissa, but then gcc aligns out the
58 * structure to 12 bytes which breaks things in math_emulate.c. Shit. I
59 * want some kind of "no-alignt" pragma or something.
60 */
/*
* Gcc��ǿ���������Ķ������⣺��ֻ��ʹ������long������������ʾ64���ص�
* ��ʱʵ��β��������gccȴ�Ὣ�ýṹ��12�ֽ������룬�⽫����math_emulate.c
* �г�������⡣����������Ҫij�ַǶ��롰no-align������ָ�
*/
61
// ��ʱʵ����Ӧ�Ľṹ��
62 typedef struct {
63 long a,b; // ��64����β��������aΪ��32λ��bΪ��32λ������1λ�̶�λ����
64 short exponent; // ָ��ֵ��
65 } temp_real;
66
// Ϊ�˽������Ӣ��ע�������ἰ�Ķ����������ƵĽṹ������ͬ����temp_real�ṹ��
67 typedef struct {
68 short m0,m1,m2,m3;
69 short exponent;
70 } temp_real_unaligned;
71
// ��temp_real����ֵa��ֵ��80387ջ�Ĵ���b (ST(i))��
72 #define real_to_real(a,b) \
73 ((*(long long *) (b) = *(long long *) (a)),((b)->exponent = (a)->exponent))
74
// ��ʵ����˫���ȣ��ṹ��
75 typedef struct {
76 long a,b; // a Ϊ��ʵ���ĵ�32λ��bΪ��32λ��
77 } long_real;
78
79 typedef long short_real; // �����ʵ�����͡�
80
// ��ʱ�����ṹ��
81 typedef struct {
82 long a,b; // a ��32�b��32�
83 short sign; // ���ű�־��
84 } temp_int;
85
// 80387Э�������ڲ���״̬�ּĴ������ݶ�Ӧ�Ľṹ�����μ�ͼ11-6��
86 struct swd {
87 int ie:1; // ��Ч�����쳣��
88 int de:1; // �ǹ���쳣��
89 int ze:1; // �����쳣��
90 int oe:1; // ������쳣��
91 int ue:1; // ������쳣��
92 int pe:1; // �����쳣��
93 int sf:1; // ջ������־����ʾ�ۼ��������ɵ��쳣��
94 int ir:1; // ir, b: ������6λ�κ�δ�����쳣����������λ��
95 int c0:1; // c0--c3: ����������
96 int c1:1;
97 int c2:1;
98 int top:3; // ָʾ80387�е�ǰλ��ջ����80λ�Ĵ�����
99 int c3:1;
100 int b:1;
101 };
102
// 80387�ڲ��Ĵ������Ʒ�ʽ������
103 #define I387 (current->tss.i387) // ���̵�80387״̬��Ϣ���μ�sched.h�ļ���
104 #define SWD (*(struct swd *) &I387.swd) // 80387��״̬�����֡�
105 #define ROUNDING ((I387.cwd >> 10) & 3) // ȡ��������������Ʒ�ʽ��
106 #define PRECISION ((I387.cwd >> 8) & 3) // ȡ�������о��ȿ��Ʒ�ʽ��
107
// ���徫����Чλ������
108 #define BITS24 0 // ������Ч����24λ�����μ�ͼ11-6��
109 #define BITS53 2 // ������Ч����53λ��
110 #define BITS64 3 // ������Ч����64λ��
111
// �������뷽ʽ������
112 #define ROUND_NEAREST 0 // ���뷽ʽ�����뵽�����ż����
113 #define ROUND_DOWN 1 // ���뷽ʽ���������ޡ�
114 #define ROUND_UP 2 // ���뷽ʽ�����������ޡ�
115 #define ROUND_0 3 // ���뷽ʽ�������0��
116
// �������塣
117 #define CONSTZ (temp_real_unaligned) {0x0000,0x0000,0x0000,0x0000,0x0000} // 0
118 #define CONST1 (temp_real_unaligned) {0x0000,0x0000,0x0000,0x8000,0x3FFF} // 1.0
119 #define CONSTPI (temp_real_unaligned) {0xC235,0x2168,0xDAA2,0xC90F,0x4000} // Pi
120 #define CONSTLN2 (temp_real_unaligned) {0x79AC,0xD1CF,0x17F7,0xB172,0x3FFE} // Loge(2)
121 #define CONSTLG2 (temp_real_unaligned) {0xF799,0xFBCF,0x9A84,0x9A20,0x3FFD} // Log10(2)
122 #define CONSTL2E (temp_real_unaligned) {0xF0BC,0x5C17,0x3B29,0xB8AA,0x3FFF} // Log2(e)
123 #define CONSTL2T (temp_real_unaligned) {0x8AFE,0xCD1B,0x784B,0xD49A,0x4000} // Log2(10)
124
// ����80387��״̬
125 #define set_IE() (I387.swd |= 1)
126 #define set_DE() (I387.swd |= 2)
127 #define set_ZE() (I387.swd |= 4)
128 #define set_OE() (I387.swd |= 8)
129 #define set_UE() (I387.swd |= 16)
130 #define set_PE() (I387.swd |= 32)
131
// ����80387����������
132 #define set_C0() (I387.swd |= 0x0100)
133 #define set_C1() (I387.swd |= 0x0200)
134 #define set_C2() (I387.swd |= 0x0400)
135 #define set_C3() (I387.swd |= 0x4000)
136
137 /* ea.c */
138
// �������ָ���в�����ʹ�õ�����Ч��ֵַ��������ָ����Ѱַģʽ�ֽڼ�����Ч��ֵַ��
// ������__info - �ж�ʱջ�����ݶ�Ӧ�ṹ��__code - ָ����롣
// ���أ���Ч��ֵַ��
139 char * ea(struct info * __info, unsigned short __code);
140
141 /* convert.c */
142
// ������������ת����������convert.c�ļ���ʵ�֡�
143 void short_to_temp(const short_real * __a, temp_real * __b);
144 void long_to_temp(const long_real * __a, temp_real * __b);
145 void temp_to_short(const temp_real * __a, short_real * __b);
146 void temp_to_long(const temp_real * __a, long_real * __b);
147 void real_to_int(const temp_real * __a, temp_int * __b);
148 void int_to_real(const temp_int * __a, temp_real * __b);
149
150 /* get_put.c */
151
// ��ȡ�����������ĺ�����
152 void get_short_real(temp_real *, struct info *, unsigned short);
153 void get_long_real(temp_real *, struct info *, unsigned short);
154 void get_temp_real(temp_real *, struct info *, unsigned short);
155 void get_short_int(temp_real *, struct info *, unsigned short);
156 void get_long_int(temp_real *, struct info *, unsigned short);
157 void get_longlong_int(temp_real *, struct info *, unsigned short);
158 void get_BCD(temp_real *, struct info *, unsigned short);
159 void put_short_real(const temp_real *, struct info *, unsigned short);
160 void put_long_real(const temp_real *, struct info *, unsigned short);
161 void put_temp_real(const temp_real *, struct info *, unsigned short);
162 void put_short_int(const temp_real *, struct info *, unsigned short);
163 void put_long_int(const temp_real *, struct info *, unsigned short);
164 void put_longlong_int(const temp_real *, struct info *, unsigned short);
165 void put_BCD(const temp_real *, struct info *, unsigned short);
166
167 /* add.c */
168
// ���渡��ӷ�ָ��ĺ�����
169 void fadd(const temp_real *, const temp_real *, temp_real *);
170
171 /* mul.c */
172
// ���渡��˷�ָ�
173 void fmul(const temp_real *, const temp_real *, temp_real *);
174
175 /* div.c */
176
// ���渡�����ָ�
177 void fdiv(const temp_real *, const temp_real *, temp_real *);
178
179 /* compare.c */
180
// �ȽϺ�����
181 void fcom(const temp_real *, const temp_real *); // ���渡��ָ��FCOM���Ƚ���������
182 void fucom(const temp_real *, const temp_real *); // ���渡��ָ��FUCOM������Ƚϡ�
183 void ftst(const temp_real *); // ���渡��ָ��FTST��ջ���ۼ�����0�Ƚϡ�
184
185 #endif
186
1 #ifndef _MM_H
2 #define _MM_H
3
4 #define PAGE_SIZE 4096 // ����1ҳ�ڴ�ҳ���ֽ�����ע����ٻ���鳤����1024�ֽڡ�
5
6 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�Ͷ��塣
7 #include <signal.h> // �ź�ͷ�ļ��������źŷ��ų������źŽṹ�Լ��źŲ�������ԭ�͡�
8
9 extern int SWAP_DEV; // �ڴ�ҳ�潻���豸�š�������mm/memory.c�ļ��У���36�С�
10
// �ӽ����豸�����д���������ڴ�ҳ�档ll_rw_page()������blk_drv/ll_rw_block.c�ļ��С�
// ����nr�����ڴ�����ҳ��ţ�buffer�Ƕ�/д��������
11 #define read_swap_page(nr,buffer) ll_rw_page(READ,SWAP_DEV,(nr),(buffer));
12 #define write_swap_page(nr,buffer) ll_rw_page(WRITE,SWAP_DEV,(nr),(buffer));
13
// �����ڴ�����ȡ��������ҳ�档����Ѿ�û�п����ڴ��ˣ���0��
14 extern unsigned long get_free_page(void);
// ��һ�������Ĺ��������ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ��������put_page()������ȫһ����
15 extern unsigned long put_dirty_page(unsigned long page,unsigned long address);
//�ͷ�������ַaddr��ʼ��1ҳ���ڴ档
16 extern void free_page(unsigned long addr);
17 void swap_free(int page_nr);
18 void swap_in(unsigned long *table_ptr);
19
//// ��ʾ�ڴ������������Ϣ�����˳���
// ���溯����ǰ�Ĺؼ���volatile���ڸ��߱�����gcc�ú������᷵�ء���������gcc��������
// һЩ�Ĵ��룬����Ҫ����ʹ������ؼ��ֿ��Ա������ijЩ��δ��ʼ�������ģ��پ�����Ϣ��
20 extern inline volatile void oom(void)
21 {
// do_exit()Ӧ��ʹ���˳����룬���������ź�ֵSIGSEGV(11) ��ֵͬ�ij����뺬���ǡ���Դ
// ��ʱ�����á�������ͬ�塣
22 printk("out of memory\n\r");
23 do_exit(SIGSEGV);
24 }
25
// ˢ��ҳ�任���ٻ���꺯����
// Ϊ����ߵ�ַת����Ч�ʣ�CPU�����ʹ�õ�ҳ�����ݴ����оƬ�и��ٻ����С����Ĺ�
// ҳ����Ϣ֮����Ҫˢ�¸û������� ����ʹ�����¼���ҳĿ¼��ַ�Ĵ���cr3 �ķ�����
// ����ˢ�¡�����eax = 0����ҳĿ¼�Ļ�ַ��
26 #define invalidate() \
27 __asm__("movl %%eax,%%cr3"::"a" (0))
28
29 /* these are not to be changed without changing head.s etc */
/* ���涨������Ҫ�Ķ�������Ҫ��head.s���ļ��е������Ϣһ��ı� */
// Linux 0.12�ں�Ĭ��֧�ֵ�����ڴ�������16MB����������Щ�������ʺϸ�����ڴ档
30 #define LOW_MEM 0x100000 // ���������ڴ�Ͷˣ�1MB����
31 extern unsigned long HIGH_MEMORY; // ���ʵ�������ڴ���߶˵�ַ��
32 #define PAGING_MEMORY (15*1024*1024) // ��ҳ�ڴ�15MB�����ڴ������15M��
33 #define PAGING_PAGES (PAGING_MEMORY>>12) // ��ҳ��������ڴ�ҳ������3840����
34 #define MAP_NR(addr) (((addr)-LOW_MEM)>>12) // ָ���ڴ��ַӳ��Ϊҳ��š�
35 #define USED 100 // ҳ�汻ռ�ñ�־���μ�449�С�
36
// �ڴ�ӳ���ֽ�ͼ��1�ֽڴ���1ҳ�ڴ棩��ÿ��ҳ���Ӧ���ֽ����ڱ�־ҳ�浱ǰ������
// ��ռ�ã���������������ӳ��15Mb���ڴ�ռ䡣�ڳ�ʼ������mem_init()�У����ڲ�
// ���������ڴ���ҳ���λ�þ���Ԥ�ȱ����ó�USED��100����
37 extern unsigned char mem_map [ PAGING_PAGES ];
38
// ���涨��ķ��ų�����ӦҳĿ¼�����ҳ��������ҳ�������е�һЩ��־λ��
39 #define PAGE_DIRTY 0x40 // λ6��ҳ���ࣨ���ģ���
40 #define PAGE_ACCESSED 0x20 // λ5��ҳ�汻���ʹ���
41 #define PAGE_USER 0x04 // λ2��ҳ�����ڣ�1-�û���0-�����û���
42 #define PAGE_RW 0x02 // λ1����дȨ��1�Cд��0�C����
43 #define PAGE_PRESENT 0x01 // λ0��ҳ����ڣ�1-���ڣ�0-�����ڡ�
44
45 #endif
46
1 #ifndef _SCHED_H
2 #define _SCHED_H
3
4 #define HZ 100 // ����ϵͳʱ�ӵδ�Ƶ��(1�ٺ��ȣ�ÿ���δ�10ms)
5
6 #define NR_TASKS 64 // ϵͳ��ͬʱ��������̣�����
7 #define TASK_SIZE 0x04000000 // ÿ������ij��ȣ�64MB����
8 #define LIBRARY_SIZE 0x00400000 // ��̬���ؿⳤ�ȣ�4MB����
9
10 #if (TASK_SIZE & 0x3fffff)
11 #error "TASK_SIZE must be multiple of 4M" // ���ȱ�����4MB�ı�����
12 #endif
13
14 #if (LIBRARY_SIZE & 0x3fffff)
15 #error "LIBRARY_SIZE must be a multiple of 4M" // �ⳤ��Ҳ������4MB�ı�����
16 #endif
17
18 #if (LIBRARY_SIZE >= (TASK_SIZE/2))
19 #error "LIBRARY_SIZE too damn big!" // ���ؿ�ij��Ȳ��ô������ȵ�һ�롣
20 #endif
21
22 #if (((TASK_SIZE>>16)*NR_TASKS) != 0x10000)
23 #error "TASK_SIZE*NR_TASKS must be 4GB" // ����*�����ܸ�������Ϊ4GB��
24 #endif
25
// �ڽ�������ַ�ռ��ж�̬�ⱻ���ص�λ�ã�60MB������
26 #define LIBRARY_OFFSET (TASK_SIZE - LIBRARY_SIZE)
27
// �����CT_TO_SECS ��CT_TO_USECS���ڰ�ϵͳ��ǰ�����ת��������ֵ����ֵ��ʾ��
28 #define CT_TO_SECS(x) ((x) / HZ)
29 #define CT_TO_USECS(x) (((x) % HZ) * 1000000/HZ)
30
31 #define FIRST_TASK task[0] // ����0�Ƚ����⣬�������������������һ�����š�
32 #define LAST_TASK task[NR_TASKS-1] // ���������е����һ������
33
34 #include <linux/head.h>
35 #include <linux/fs.h>
36 #include <linux/mm.h>
37 #include <sys/param.h>
38 #include <sys/time.h>
39 #include <sys/resource.h>
40 #include <signal.h>
41
42 #if (NR_OPEN > 32)
43 #error "Currently the close-on-exec-flags and select masks are in one long, max 32 files/proc"
44 #endif
45
// ���ﶨ���˽�������ʱ���ܴ���״̬��
46 #define TASK_RUNNING 0 // ���������������������
47 #define TASK_INTERRUPTIBLE 1 // ���̴��ڿ��жϵȴ�״̬��
48 #define TASK_UNINTERRUPTIBLE 2 // ���̴��ڲ����жϵȴ�״̬����Ҫ����I/O�����ȴ���
49 #define TASK_ZOMBIE 3 // ���̴��ڽ���״̬���Ѿ�ֹͣ���У��������̻�û���źš�
50 #define TASK_STOPPED 4 // ������ֹͣ��
51
52 #ifndef NULL
53 #define NULL ((void *) 0) // ����NULLΪ��ָ�롣
54 #endif
55
// ���ƽ��̵�ҳĿ¼ҳ����Linus��Ϊ�����ں�����ӵĺ���֮һ��( mm/memory.c, 105 )
56 extern int copy_page_tables(unsigned long from, unsigned long to, long size);
// �ͷ�ҳ����ָ�����ڴ�鼰ҳ��������( mm/memory.c, 150 )
57 extern int free_page_tables(unsigned long from, unsigned long size);
58
// ���ȳ���ij�ʼ��������( kernel/sched.c, 385 )
59 extern void sched_init(void);
// ���̵��Ⱥ�����( kernel/sched.c, 104 )
60 extern void schedule(void);
// �쳣(����)�жϴ�����ʼ�������������жϵ����Ų������ж������źš�( kernel/traps.c, 181 )
61 extern void trap_init(void);
// ��ʾ�ں˳�����Ϣ��Ȼ�������ѭ����( kernel/panic.c, 16 )��
62 extern void panic(const char * str);
// ��tty��дָ�����ȵ��ַ�����( kernel/chr_drv/tty_io.c, 290 )��
63 extern int tty_write(unsigned minor,char * buf,int count);
64
65 typedef int (*fn_ptr)(); // ���庯��ָ�����͡�
66
// ��������ѧЭ������ʹ�õĽṹ����Ҫ���ڱ�������л�ʱi387��ִ��״̬��Ϣ��
67 struct i387_struct {
68 long cwd; // ������(Control word)��
69 long swd; // ״̬��(Status word)��
70 long twd; // �����(Tag word)��
71 long fip; // Э����������ָ�롣
72 long fcs; // Э����������μĴ�����
73 long foo; // �ڴ��������ƫ��λ�á�
74 long fos; // �ڴ�������Ķ�ֵ��
75 long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */
76 }; /* 8��10�ֽڵ�Э�������ۼ�����*/
77
// ����״̬�����ݽṹ��
78 struct tss_struct {
79 long back_link; /* 16 high bits zero */
80 long esp0;
81 long ss0; /* 16 high bits zero */
82 long esp1;
83 long ss1; /* 16 high bits zero */
84 long esp2;
85 long ss2; /* 16 high bits zero */
86 long cr3;
87 long eip;
88 long eflags;
89 long eax,ecx,edx,ebx;
90 long esp;
91 long ebp;
92 long esi;
93 long edi;
94 long es; /* 16 high bits zero */
95 long cs; /* 16 high bits zero */
96 long ss; /* 16 high bits zero */
97 long ds; /* 16 high bits zero */
98 long fs; /* 16 high bits zero */
99 long gs; /* 16 high bits zero */
100 long ldt; /* 16 high bits zero */
101 long trace_bitmap; /* bits: trace 0, bitmap 16-31 */
102 struct i387_struct i387;
103 };
104
// �����������̣����ݽṹ�����Ϊ������������
// long state ���������״̬��-1�������У�0������(����)��>0��ֹͣ����
// long counter ��������ʱ�����(�ݼ�)���δ�����������ʱ��Ƭ��
// long priority ������������ʼ����ʱcounter=priority��Խ������Խ����
// long signal �ź�λͼ��ÿ������λ����һ���źţ��ź�ֵ=λƫ��ֵ+1��
// struct sigaction sigaction[32] �ź�ִ�����Խṹ����Ӧ�źŽ�Ҫִ�еIJ����ͱ�־��Ϣ��
// long blocked �����ź������루��Ӧ�ź�λͼ����
// -------------------
// int exit_code ����ִ��ֹͣ���˳��룬�丸���̻�ȡ��
// unsigned long start_code ����ε�ַ��
// unsigned long end_code ���볤�ȣ��ֽ�������
// unsigned long end_data ���볤�� + ���ݳ��ȣ��ֽ�������
// unsigned long brk �ܳ��ȣ��ֽ�������
// unsigned long start_stack ��ջ�ε�ַ��
// long pid ���̱�ʶ��(���̺�)��
// long pgrp ������š�
// long session �Ự�š�
// long leader �Ự���졣
// int groups[NGROUPS] ����������š�һ�����̿����ڶ���顣
// task_struct *p_pptr ָ���̵�ָ�롣
// task_struct *p_cptr ָ�������ӽ��̵�ָ�롣
// task_struct *p_ysptr ָ����Լ��������ڽ��̵�ָ�롣
// task_struct *p_osptr ָ����Լ��紴�������ڽ��̵�ָ�롣
// unsigned short uid �û���ʶ�ţ��û�id����
// unsigned short euid ��Ч�û�id��
// unsigned short suid ������û�id��
// unsigned short gid ���ʶ�ţ���id����
// unsigned short egid ����id��
// unsigned short sgid �������id��
// long timeout �ں˶�ʱ��ʱֵ��
// long alarm ������ʱֵ���δ�������
// long utime �û�̬����ʱ�䣨�δ�������
// long stime ϵͳ̬����ʱ�䣨�δ�������
// long cutime �ӽ����û�̬����ʱ�䡣
// long cstime �ӽ���ϵͳ̬����ʱ�䡣
// long start_time ���̿�ʼ����ʱ�̡�
// struct rlimit rlim[RLIM_NLIMITS] ������Դʹ��ͳ�����顣
// unsigned int flags; �����̵ı�־���������149�п�ʼ���壨��δʹ�ã���
// unsigned short used_math ��־���Ƿ�ʹ����Э��������
// ------------------------
// int tty ����ʹ��tty�ն˵����豸�š�-1��ʾû��ʹ�á�
// unsigned short umask �ļ�������������λ��
// struct m_inode * pwd ��ǰ����Ŀ¼i�ڵ�ṹָ�롣
// struct m_inode * root ��Ŀ¼i�ڵ�ṹָ�롣
// struct m_inode * executable ִ���ļ�i�ڵ�ṹָ�롣
// struct m_inode * library �����ؿ��ļ�i�ڵ�ṹָ�롣
// unsigned long close_on_exec ִ��ʱ�ر��ļ����λͼ��־�����μ�include/fcntl.h��
// struct file * filp[NR_OPEN] �ļ��ṹָ��������32�����ż����ļ���������ֵ��
// struct desc_struct ldt[3] �ֲ�����������0-�գ�1-�����cs��2-���ݺͶ�ջ��ds&ss��
// struct tss_struct tss ���̵�����״̬����Ϣ�ṹ��
// ======================================
105 struct task_struct {
106 /* these are hardcoded - don't touch */
107 long state; /* -1 unrunnable, 0 runnable, >0 stopped */
108 long counter;
109 long priority;
110 long signal;
111 struct sigaction sigaction[32];
112 long blocked; /* bitmap of masked signals */
113 /* various fields */
114 int exit_code;
115 unsigned long start_code,end_code,end_data,brk,start_stack;
116 long pid,pgrp,session,leader;
117 int groups[NGROUPS];
118 /*
119 * pointers to parent process, youngest child, younger sibling,
120 * older sibling, respectively. (p->father can be replaced with
121 * p->p_pptr->pid)
122 */
123 struct task_struct *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
124 unsigned short uid,euid,suid;
125 unsigned short gid,egid,sgid;
126 unsigned long timeout,alarm;
127 long utime,stime,cutime,cstime,start_time;
128 struct rlimit rlim[RLIM_NLIMITS];
129 unsigned int flags; /* per process flags, defined below */
130 unsigned short used_math;
131 /* file system info */
132 int tty; /* -1 if no tty, so it must be signed */
133 unsigned short umask;
134 struct m_inode * pwd;
135 struct m_inode * root;
136 struct m_inode * executable;
137 struct m_inode * library;
138 unsigned long close_on_exec;
139 struct file * filp[NR_OPEN];
140 /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */
141 struct desc_struct ldt[3];
142 /* tss for this task */
143 struct tss_struct tss;
144 };
145
146 /*
147 * Per process flags
148 */
/* ÿ�����̵ı�־ */ /* ��ӡ���뾯����Ϣ����δʵ�֣�������486 */
149 #define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */
150 /* Not implemented yet, only for 486*/
151
152 /*
153 * INIT_TASK is used to set up the first task table, touch at
154 * your own risk!. Base=0, limit=0x9ffff (=640kB)
155 */
/*
* INIT_TASK�������õ�1��������������ģ������Ը�J��
* ��ַBase = 0���γ�limit = 0x9ffff��=640kB����
*/
// ��Ӧ��������ṹ�ĵ�1���������Ϣ��
156 #define INIT_TASK \
157 /* state etc */ { 0,15,15, \ // state, counter, priority
158 /* signals */ 0,{{},},0, \ // signal, sigaction[32], blocked
159 /* ec,brk... */ 0,0,0,0,0,0, \ // exit_code,start_code,end_code,end_data,brk,start_stack
160 /* pid etc.. */ 0,0,0,0, \ // pid, pgrp, session, leader
161 /* suppl grps*/ {NOGROUP,}, \ // groups[]
162 /* proc links*/ &init_task.task,0,0,0, \ // p_pptr, p_cptr, p_ysptr, p_osptr
163 /* uid etc */ 0,0,0,0,0,0, \ // uid, euid, suid, gid, egid, sgid
164 /* timeout */ 0,0,0,0,0,0,0, \ // alarm,utime,stime,cutime,cstime,start_time,used_math
165 /* rlimits */ { {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
166 {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}, \
167 {0x7fffffff, 0x7fffffff}, {0x7fffffff, 0x7fffffff}}, \
168 /* flags */ 0, \ // flags
169 /* math */ 0, \ // used_math, tty,umask,pwd,root,executable,close_on_exec
170 /* fs info */ -1,0022,NULL,NULL,NULL,NULL,0, \
171 /* filp */ {NULL,}, \ // filp[20]
172 { \ // ldt[3]
173 {0,0}, \
174 /* ldt */ {0x9f,0xc0fa00}, \ // ���볤640K����ַ0x0��G=1��D=1��DPL=3��P=1 TYPE=0xa
175 {0x9f,0xc0f200}, \ // ���ݳ�640K����ַ0x0��G=1��D=1��DPL=3��P=1 TYPE=0x2
176 }, \
177 /*tss*/ {0,PAGE_SIZE+(long)&init_task,0x10,0,0,0,0,(long)&pg_dir,\ // tss
178 0,0,0,0,0,0,0,0, \
179 0,0,0x17,0x17,0x17,0x17,0x17,0x17, \
180 _LDT(0),0x80000000, \
181 {} \
182 }, \
183 }
184
185 extern struct task_struct *task[NR_TASKS]; // ����ָ�����顣
186 extern struct task_struct *last_task_used_math; // ��һ��ʹ�ù�Э�������Ľ��̡�
187 extern struct task_struct *current; // ��ǰ���н��̽ṹָ�������
188 extern unsigned long volatile jiffies; // �ӿ�����ʼ����ĵδ�����10ms/�δ𣩡�
189 extern unsigned long startup_time; // ����ʱ�䡣��1970:0:0:0��ʼ��ʱ��������
190 extern int jiffies_offset; // �����ۼ���Ҫ������ʱ���������
191
192 #define CURRENT_TIME (startup_time+(jiffies+jiffies_offset)/HZ) // ��ǰʱ�䣨��������
193
// ���Ӷ�ʱ����������ʱʱ��jiffies�δ�������ʱ��ʱ���ú���*fn()����( kernel/sched.c )
194 extern void add_timer(long jiffies, void (*fn)(void));
// �����жϵĵȴ�˯�ߡ�( kernel/sched.c )
195 extern void sleep_on(struct task_struct ** p);
// ���жϵĵȴ�˯�ߡ�( kernel/sched.c )
196 extern void interruptible_sleep_on(struct task_struct ** p);
// ��ȷ����˯�ߵĽ��̡�( kernel/sched.c )
197 extern void wake_up(struct task_struct ** p);
// ��鵱ǰ�����Ƿ���ָ�����û���grp�С�
198 extern int in_group_p(gid_t grp);
199
200 /*
201 * Entry into gdt where to find first TSS. 0-nul, 1-cs, 2-ds, 3-syscall
202 * 4-TSS0, 5-LDT0, 6-TSS1 etc ...
203 */
/*
* Ѱ�ҵ�1��TSS��ȫ�ֱ��е���ڡ�0-û����nul��1-�����cs��2-���ݶ�ds��3-ϵͳ��syscall
* 4-����״̬��TSS0��5-�ֲ���LTD0��6-����״̬��TSS1���ȡ�
*/
// �Ӹ�Ӣ��ע�Ϳ��Բ��뵽��Linus��ʱ�����ϵͳ���õĴ���ר�ŷ���GDT���е�4�������Ķ��С�
// ��������û�������������Ǿ�һֱ��GDT���е�4�������������syscall�������һ�ԡ�
// ���涨��꣺ȫ�ֱ��е�1������״̬��(TSS)��������ѡ��������š�
204 #define FIRST_TSS_ENTRY 4
// ȫ�ֱ��е�1���ֲ���������(LDT)��������ѡ��������š�
205 #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)
// �궨�壬������ȫ�ֱ��е�n�������TSS����������ѡ���ֵ��ƫ��������
// ��ÿ��������ռ8�ֽڣ����FIRST_TSS_ENTRY<<3 ��ʾ����������GDT���е���ʼƫ��λ�á�
// ��Ϊÿ������ʹ��1��TSS��1��LDT����������ռ��16�ֽڣ������Ҫ n<<4 ����ʾ��Ӧ
// TSS��ʼλ�á��ú�õ���ֵ����Ҳ�Ǹ�TSS��ѡ���ֵ��
206 #define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
// �궨�壬������ȫ�ֱ��е�n�������LDT����������ѡ���ֵ��ƫ��������
207 #define _LDT(n) ((((unsigned long) n)<<4)+(FIRST_LDT_ENTRY<<3))
// �궨�壬�ѵ�n�������TSS��ѡ������ص�����Ĵ���TR�С�
208 #define ltr(n) __asm__("ltr %%ax"::"a" (_TSS(n)))
// �궨�壬�ѵ�n�������LDT��ѡ������ص��ֲ����������Ĵ���LDTR�С�
209 #define lldt(n) __asm__("lldt %%ax"::"a" (_LDT(n)))
// ȡ��ǰ�������������ţ������������е�����ֵ������̺�pid��ͬ����
// ���أ�n - ��ǰ����š�����( kernel/traps.c )��
210 #define str(n) \
211 __asm__("str %%ax\n\t" \ // ������Ĵ�����TSS�ε�ѡ������Ƶ�ax�С�
212 "subl %2,%%eax\n\t" \ // (eax - FIRST_TSS_ENTRY*8)��eax
213 "shrl $4,%%eax" \ // (eax/16)��eax = ��ǰ����š�
214 :"=a" (n) \
215 :"a" (0),"i" (FIRST_TSS_ENTRY<<3))
216 /*
217 * switch_to(n) should switch tasks to task nr n, first
218 * checking that n isn't the current task, in which case it does nothing.
219 * This also clears the TS-flag if the task we switched to has used
220 * tha math co-processor latest.
221 */
/*
* switch_to(n)���л���ǰ��������nr����n�����ȼ������n���ǵ�ǰ����
* �������ʲôҲ�����˳�����������л���������������ϴ����У�ʹ�ù���ѧ
* Э�������Ļ������踴λ���ƼĴ���cr0�е�TS��־��
*/
// ��ת��һ�������TSS��ѡ�����ɵĵ�ַ�������CPU���������л�������
// ���룺%0 - ָ��__tmp�� %1 - ָ��__tmp.b�������ڴ����TSS��ѡ�����
// dx - ������n��TSS��ѡ����� ecx - ������n������ṹָ��task[n]��
// ������ʱ���ݽṹ__tmp�����齨177��Զ��ת��far jump��ָ��IJ��������ò�������4�ֽ�
// ƫ�Ƶ�ַ��2�ֽڵĶ�ѡ�����ɡ����__tmp��a��ֵ��32λƫ��ֵ����b�ĵ�2�ֽ�����
// TSS�ε�ѡ�������2�ֽڲ��ã�����ת��TSS��ѡ�������������л�����TSS��Ӧ�Ľ��̡�
// ������������л��ij���ת��aֵ���á�177���ϵ��ڴ�����תָ��ʹ��6�ֽڲ�������Ϊ��
// תĿ�ĵصij�ָ�룬���ʽΪ��jmp 16λ��ѡ�����32λƫ��ֵ�������ڴ��в������ı�ʾ˳
// �������������෴�������л�����֮�����ж�ԭ�����ϴ�ִ���Ƿ�ʹ�ù�Э������ʱ����ͨ��
// ��ԭ����ָ���뱣����last_task_used_math�����е��ϴ�ʹ�ù�Э����������ָ����бȽ϶�
// �����ģ��μ��ļ�kernel/sched.c���й�math_state_restore()������˵����
222 #define switch_to(n) {\
223 struct {long a,b;} __tmp; \
224 __asm__("cmpl %%ecx,_current\n\t" \ // ����n�ǵ�ǰ������?(current ==task[n]?)
225 "je 1f\n\t" \ // �ǣ���ʲô���������˳���
226 "movw %%dx,%1\n\t" \ // ��������TSS��16λѡ�������__tmp.b�С�
227 "xchgl %%ecx,_current\n\t" \ // current = task[n]��ecx = �����������
228 "ljmp %0\n\t" \ // ִ�г���ת��*&__tmp����������л���
// �������л�������Ż����ִ���������䡣
229 "cmpl %%ecx,_last_task_used_math\n\t" \ // ԭ�����ϴ�ʹ�ù�Э��������
230 "jne 1f\n\t" \ // û������ת���˳���
231 "clts\n" \ // ԭ�����ϴ�ʹ�ù�Э������������cr0�е�����
232 "1:" \ // �л���־TS��
233 ::"m" (*&__tmp.a),"m" (*&__tmp.b), \
234 "d" (_TSS(n)),"c" ((long) task[n])); \
235 }
236
// ҳ���ַ���������ں˴�����û���κεط�����!!��
237 #define PAGE_ALIGN(n) (((n)+0xfff)&0xfffff000)
238
// ����λ�ڵ�ַaddr���������еĸ�����ַ�ֶ�(����ַ��base)��
// %0 - ��ַaddrƫ��2��%1 - ��ַaddrƫ��4��%2 - ��ַaddrƫ��7��edx - ����ַbase��
239 #define _set_base(addr,base) \
240 __asm__("movw %%dx,%0\n\t" \ // ��ַbase��16λ(λ15-0)��[addr+2]��
241 "rorl $16,%%edx\n\t" \ // edx�л�ַ��16λ(λ31-16)��dx��
242 "movb %%dl,%1\n\t" \ // ��ַ��16λ�еĵ�8λ(λ23-16)��[addr+4]��
243 "movb %%dh,%2" \ // ��ַ��16λ�еĸ�8λ(λ31-24)��[addr+7]��
244 ::"m" (*((addr)+2)), \
245 "m" (*((addr)+4)), \
246 "m" (*((addr)+7)), \
247 "d" (base) \
248 :"dx") // ����gcc������edx�Ĵ����е�ֵ�ѱ�Ƕ�������ı��ˡ�
249
// ����λ�ڵ�ַaddr���������еĶ����ֶ�(�γ���limit)��
// %0 - ��ַaddr��%1 - ��ַaddrƫ��6����edx - �γ�ֵlimit��
250 #define _set_limit(addr,limit) \
251 __asm__("movw %%dx,%0\n\t" \ // �γ�limit��16λ(λ15-0)��[addr]��
252 "rorl $16,%%edx\n\t" \ // edx�еĶγ���4λ(λ19-16)��dl��
253 "movb %1,%%dh\n\t" \ // ȡԭ[addr+6]�ֽ���dh�����и�4λ��Щ��־��
254 "andb $0xf0,%%dh\n\t" \ // ��dh�ĵ�4λ(����Ŷγ���λ19-16)��
255 "orb %%dh,%%dl\n\t" \ // ��ԭ��4λ��־�Ͷγ��ĸ�4λ(λ19-16)�ϳ�1�ֽڣ�
256 "movb %%dl,%1" \ // ����[addr+6]����
257 ::"m" (*(addr)), \
258 "m" (*((addr)+6)), \
259 "d" (limit) \
260 :"dx")
261
// ���þֲ�����������ldt�������Ļ���ַ�ֶΡ�
262 #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
// ���þֲ�����������ldt�������Ķγ��ֶΡ�
263 #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
264
// �ӵ�ַaddr����������ȡ�λ���ַ��������_set_base()�����෴��
// edx - ��Ż���ַ(__base)��%1 - ��ַaddrƫ��2��%2 - ��ַaddrƫ��4��%3 - addrƫ��7��
265 #define _get_base(addr) ({\
266 unsigned long __base; \
267 __asm__("movb %3,%%dh\n\t" \ // ȡ[addr+7]����ַ��16λ�ĸ�8λ(λ31-24)��dh��
268 "movb %2,%%dl\n\t" \ // ȡ[addr+4]����ַ��16λ�ĵ�8λ(λ23-16)��dl��
269 "shll $16,%%edx\n\t" \ // ����ַ��16λ�Ƶ�edx�и�16λ����
270 "movw %1,%%dx" \ // ȡ[addr+2]����ַ��16λ(λ15-0)��dx��
271 :"=d" (__base) \ // �Ӷ�edx�к���32λ�Ķλ���ַ��
272 :"m" (*((addr)+2)), \
273 "m" (*((addr)+4)), \
274 "m" (*((addr)+7))); \
275 __base;})
276
// ȡ�ֲ�����������ldt��ָ���������еĻ���ַ��
277 #define get_base(ldt) _get_base( ((char *)&(ldt)) )
278
// ȡ��ѡ���segmentָ�����������еĶ���ֵ��
// ָ��lsl��Load Segment Limit��д������ָ������������ȡ����ɢ��������λƴ��������
// ����ֵ����ָ���Ĵ����С����õĶ�����ʵ���ֽ�����1��������ﻹ��Ҫ��1��ŷ��ء�
// %0 - ��Ŷγ�ֵ(�ֽ���)��%1 - ��ѡ���segment��
279 #define get_limit(segment) ({ \
280 unsigned long __limit; \
281 __asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \
282 __limit;})
283
284 #endif
285
1 /*
2 * Why isn't this a .c file? Enquiring minds....
3 */
/*
* Ϊʲô�ⲻ��һ��.c�ļ��������Խ��Լ�����....
*/
4
5 extern int sys_setup(); // 0 - ϵͳ������ʼ�����ú����� (kernel/blk_drv/hd.c)
6 extern int sys_exit(); // 1 - �����˳��� (kernel/exit.c )
7 extern int sys_fork(); // 2 - �������̡� (kernel/system_call.s)
8 extern int sys_read(); // 3 - ����� (fs/read_write.c)
9 extern int sys_write(); // 4 - д�ļ��� (fs/read_write.c)
10 extern int sys_open(); // 5 - ����� (fs/open.c)
11 extern int sys_close(); // 6 - �ر��ļ��� (fs/open.c)
12 extern int sys_waitpid(); // 7 - �ȴ�������ֹ�� (kernel/exit.c)
13 extern int sys_creat(); // 8 - ������� (fs/open.c)
14 extern int sys_link(); // 9 - ����һ���ļ���Ӳ���ӡ� (fs/namei.c)
15 extern int sys_unlink(); // 10 - ɾ��һ���ļ���(��ɾ���ļ�)�� (fs/namei.c)
16 extern int sys_execve(); // 11 - ִ�г��� (kernel/system_call.s)
17 extern int sys_chdir(); // 12 - ���ĵ�ǰĿ¼�� (fs/open.c)
18 extern int sys_time(); // 13 - ȡ��ǰʱ�䡣 (kernel/sys.c)
19 extern int sys_mknod(); // 14 - ������/�ַ������ļ��� (fs/namei.c)
20 extern int sys_chmod(); // 15 - ���ļ����ԡ� (fs/open.c)
21 extern int sys_chown(); // 16 - ���ļ������������顣 (fs/open.c)
22 extern int sys_break(); // 17 - (kernel/sys.c)*
23 extern int sys_stat(); // 18 - ʹ��·����ȡ�ļ�״̬��Ϣ��(fs/stat.c)
24 extern int sys_lseek(); // 19 - ���¶�λ��/д�ļ�ƫ�ơ� (fs/read_write.c)
25 extern int sys_getpid(); // 20 - ȡ����id�� (kernel/sched.c)
26 extern int sys_mount(); // 21 - ��װ�ļ�ϵͳ�� (fs/super.c)
27 extern int sys_umount(); // 22 - ж���ļ�ϵͳ�� (fs/super.c)
28 extern int sys_setuid(); // 23 - ���ý����û�id�� (kernel/sys.c)
29 extern int sys_getuid(); // 24 - ȡ�����û�id�� (kernel/sched.c)
30 extern int sys_stime(); // 25 - ����ϵͳʱ�����ڡ� (kernel/sys.c)*
31 extern int sys_ptrace(); // 26 - ������ԡ� (kernel/sys.c)*
32 extern int sys_alarm(); // 27 - ������ (kernel/sched.c)
33 extern int sys_fstat(); // 28 - ʹ���ļ����ȡ�ļ���״̬��Ϣ��(fs/stat.c)
34 extern int sys_pause(); // 29 - ��ͣ�������С� (kernel/sched.c)
35 extern int sys_utime(); // 30 - �ı��ļ��ķ��ʺ���ʱ�䡣(fs/open.c)
36 extern int sys_stty(); // 31 - ���ն������á� (kernel/sys.c)*
37 extern int sys_gtty(); // 32 - ȡ�ն���������Ϣ�� (kernel/sys.c)*
38 extern int sys_access(); // 33 - ����û���һ���ļ��ķ���Ȩ�ޡ�(fs/open.c)
39 extern int sys_nice(); // 34 - ���ý���ִ������Ȩ�� (kernel/sched.c)
40 extern int sys_ftime(); // 35 - ȡ���ں�ʱ�䡣 (kernel/sys.c)*
41 extern int sys_sync(); // 36 - ͬ�����ٻ������豸�����ݡ�(fs/buffer.c)
42 extern int sys_kill(); // 37 - ��ֹһ�����̡� (kernel/exit.c)
43 extern int sys_rename(); // 38 - ��������� (kernel/sys.c)*
44 extern int sys_mkdir(); // 39 - ����Ŀ¼�� (fs/namei.c)
45 extern int sys_rmdir(); // 40 - ɾ��Ŀ¼�� (fs/namei.c)
46 extern int sys_dup(); // 41 - ���������� (fs/fcntl.c)
47 extern int sys_pipe(); // 42 - �����ܵ��� (fs/pipe.c)
48 extern int sys_times(); // 43 - ȡ����ʱ�䡣 (kernel/sys.c)
49 extern int sys_prof(); // 44 - ����ִ��ʱ������ (kernel/sys.c)*
50 extern int sys_brk(); // 45 - �����ݶγ��ȡ� (kernel/sys.c)
51 extern int sys_setgid(); // 46 - ���ý�����id�� (kernel/sys.c)
52 extern int sys_getgid(); // 47 - ȡ������id�� (kernel/sched.c)
53 extern int sys_signal(); // 48 - �źŴ����� (kernel/signal.c)
54 extern int sys_geteuid(); // 49 - ȡ������Ч�û�id�� (kenrl/sched.c)
55 extern int sys_getegid(); // 50 - ȡ������Ч��id�� (kenrl/sched.c)
56 extern int sys_acct(); // 51 - ���̼��ʡ� (kernel/sys.c)*
57 extern int sys_phys(); // 52 - (kernel/sys.c)*
58 extern int sys_lock(); // 53 - (kernel/sys.c)*
59 extern int sys_ioctl(); // 54 - �豸����������ơ� (fs/ioctl.c)
60 extern int sys_fcntl(); // 55 - �ļ�������Ʋ����� (fs/fcntl.c)
61 extern int sys_mpx(); // 56 - (kernel/sys.c)*
62 extern int sys_setpgid(); // 57 - ���ý�����id�� (kernel/sys.c)
63 extern int sys_ulimit(); // 58 - ͳ�ƽ���ʹ����Դ����� (kernel/sys.c)
64 extern int sys_uname(); // 59 - ��ʾϵͳ��Ϣ�� (kernel/sys.c)
65 extern int sys_umask(); // 60 - ȡĬ���ļ����������롣 (kernel/sys.c)
66 extern int sys_chroot(); // 61 - �ı��Ŀ¼�� (fs/open.c)
67 extern int sys_ustat(); // 62 - ȡ�ļ�ϵͳ��Ϣ�� (fs/open.c)
68 extern int sys_dup2(); // 63 - ���������� (fs/fcntl.c)
69 extern int sys_getppid(); // 64 - ȡ������id�� (kernel/sched.c)
70 extern int sys_getpgrp(); // 65 - ȡ������id������getpgid(0)��(kernel/sys.c)
71 extern int sys_setsid(); // 66 - ���»Ự�����г��� (kernel/sys.c)
72 extern int sys_sigaction(); // 67 - �ı��źŴ������̡� (kernel/signal.c)
73 extern int sys_sgetmask(); // 68 - ȡ�ź������롣 (kernel/signal.c)
74 extern int sys_ssetmask(); // 69 - �����ź������롣 (kernel/signal.c)
75 extern int sys_setreuid(); // 70 - ������ʵ��/����Ч�û�id�� (kernel/sys.c)
76 extern int sys_setregid(); // 71 - ������ʵ��/����Ч��id�� (kernel/sys.c)
77 extern int sys_sigpending(); // 73 - �����δ�������źš� (kernel/signal.c)
78 extern int sys_sigsuspend(); // 72 - ʹ���������������̡� (kernel/signal.c)
79 extern int sys_sethostname(); // 74 - ������������ (kernel/sys.c)
80 extern int sys_setrlimit(); // 75 - ������Դʹ�����ơ� (kernel/sys.c)
81 extern int sys_getrlimit(); // 76 - ȡ�ý���ʹ����Դ�����ơ� (kernel/sys.c)
82 extern int sys_getrusage(); // 77 -
83 extern int sys_gettimeofday(); // 78 - ��ȡ����ʱ�䡣 (kernel/sys.c)
84 extern int sys_settimeofday(); // 79 - ���õ���ʱ�䡣 (kernel/sys.c)
85 extern int sys_getgroups(); // 80 - ȡ�ý����������ʶ�š� (kernel/sys.c)
86 extern int sys_setgroups(); // 81 - ���ý������ʶ�����顣 (kernel/sys.c)
87 extern int sys_select(); // 82 - �ȴ��ļ�������״̬�ı䡣 (fs/select.c)
88 extern int sys_symlink(); // 83 - �����������ӡ� (fs/namei.c��767)
89 extern int sys_lstat(); // 84 - ȡ���������ļ�״̬�� (fs/stat.c��47)
90 extern int sys_readlink(); // 85 - ��ȡ���������ļ���Ϣ�� (fs/stat.c��69)
91 extern int sys_uselib(); // 86 - ѡ�����⡣ (fs/exec.c, 42)
92
// ϵͳ���ú���ָ���������ϵͳ�����жϴ�������(int 0x80)����Ϊ��ת����
93 fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
94 sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
95 sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
96 sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
97 sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
98 sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
99 sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
100 sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
101 sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
102 sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
103 sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
104 sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
105 sys_setreuid,sys_setregid, sys_sigsuspend, sys_sigpending, sys_sethostname,
106 sys_setrlimit, sys_getrlimit, sys_getrusage, sys_gettimeofday,
107 sys_settimeofday, sys_getgroups, sys_setgroups, sys_select, sys_symlink,
108 sys_lstat, sys_readlink, sys_uselib };
109
110 /* So we don't have to do any more manual updating.... */
/* ����������������Ǿ������ֹ�����ϵͳ������Ŀ�� */
111 int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
112
1 /*
2 * 'tty.h' defines some structures used by tty_io.c and some defines.
3 *
4 * NOTE! Don't touch this without checking that nothing in rs_io.s or
5 * con_io.s breaks. Some constants are hardwired into the system (mainly
6 * offsets into 'tty_queue'
7 */
/*
* 'tty.h'�ж�����tty_io.c����ʹ�õ�ijЩ�ṹ������һЩ���塣
*
* ע�⣡��������Ķ���ʱ��һ��Ҫ���rs_io.s��con_io.s�����в���������⡣
* ��ϵͳ����Щ������ֱ��д�ڳ����еģ���Ҫ��һЩtty_queue�е�ƫ��ֵ����
*/
8
9 #ifndef _TTY_H
10 #define _TTY_H
11
12 #define MAX_CONSOLES 8 // ����������̨������
13 #define NR_SERIALS 2 // �����ն�������
14 #define NR_PTYS 4 // α�ն�������
15
16 extern int NR_CONSOLES; // �������̨������
17
18 #include <termios.h> // �ն������������ͷ�ļ�����Ҫ��������첽ͨ�ſڵ��ն˽ӿڡ�
19
20 #define TTY_BUF_SIZE 1024 // tty�������������������
21
// tty�ַ�����������ݽṹ������tty_struc�ṹ�еĶ���д�������淶��������С�
22 struct tty_queue {
23 unsigned long data; // ���л������к����ַ�����ֵ�����ǵ�ǰ�ַ�������
// ���ڴ����նˣ����Ŵ��ж˿ڵ�ַ��
24 unsigned long head; // ������������ͷָ�롣
25 unsigned long tail; // ������������βָ�롣
26 struct task_struct * proc_list; // �ȴ������еĽ����б���
27 char buf[TTY_BUF_SIZE]; // ���еĻ�������
28 };
29
30 #define IS_A_CONSOLE(min) (((min) & 0xC0) == 0x00) // ��һ�������նˡ�
31 #define IS_A_SERIAL(min) (((min) & 0xC0) == 0x40) // ��һ�������նˡ�
32 #define IS_A_PTY(min) ((min) & 0x80) // ��һ��α�նˡ�
33 #define IS_A_PTY_MASTER(min) (((min) & 0xC0) == 0x80) // ��һ����α�նˡ�
34 #define IS_A_PTY_SLAVE(min) (((min) & 0xC0) == 0xC0) // ��һ����α�նˡ�
35 #define PTY_OTHER(min) ((min) ^ 0x40) // ����α�նˡ�
36
// ���¶�����tty�ȴ������л����������꺯������tail��ǰ��head�ںμ�tty_io.c��ͼ����
// a������ָ��ǰ��1�ֽڣ����ѳ����������Ҳ࣬��ָ��ѭ����
37 #define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))
// a������ָ�����1�ֽڣ���ѭ����
38 #define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))
// ���ָ�����еĻ�������
39 #define EMPTY(a) ((a)->head == (a)->tail)
// ���������ɴ���ַ��ij��ȣ����������ȣ���
40 #define LEFT(a) (((a)->tail-(a)->head-1)&(TTY_BUF_SIZE-1))
// �����������һ��λ�á�
41 #define LAST(a) ((a)->buf[(TTY_BUF_SIZE-1)&((a)->head-1)])
// �������������Ϊ1�Ļ�����
42 #define FULL(a) (!LEFT(a))
// ���������Ѵ���ַ��ij��ȣ��ַ�������
43 #define CHARS(a) (((a)->head-(a)->tail)&(TTY_BUF_SIZE-1))
// ��queue�����������ȡһ�ַ�(��tail��������tail+=1)��
44 #define GETCH(queue,c) \
45 (void)({c=(queue)->buf[(queue)->tail];INC((queue)->tail);})
// ��queue����������з���һ�ַ�����head��������head+=1����
46 #define PUTCH(c,queue) \
47 (void)({(queue)->buf[(queue)->head]=(c);INC((queue)->head);})
48
// �ж��ն˼����ַ����͡�
49 #define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR]) // �жϷ������ж��ź�SIGINT��
50 #define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT]) // �˳��������˳��ź�SIGQUIT��
51 #define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE]) // ������������һ���ַ���
52 #define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL]) // ɾ���С�ɾ��һ���ַ���
53 #define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF]) // ���������
54 #define START_CHAR(tty) ((tty)->termios.c_cc[VSTART]) // ��ʼ�����ָ������
55 #define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP]) // ֹͣ����ֹͣ�����
56 #define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP]) // ��������������ź�SIGTSTP��
57
// tty���ݽṹ��
58 struct tty_struct {
59 struct termios termios; // �ն�io���ԺͿ����ַ����ݽṹ��
60 int pgrp; // ���������顣
61 int session; // �Ự�š�
62 int stopped; // ֹͣ��־��
63 void (*write)(struct tty_struct * tty); // ttyд����ָ�롣
64 struct tty_queue *read_q; // tty������
65 struct tty_queue *write_q; // tty���
66 struct tty_queue *secondary; // tty��������(��Ź淶ģʽ�ַ�����)��
67 }; // �ɳ�Ϊ�淶(��)ģʽ���С�
68
69 extern struct tty_struct tty_table[]; // tty�ṹ���顣
70 extern int fg_console; // ǰ̨����̨�š�
71
// �����ն�������tty_table[] ��ȡ��Ӧ�ն˺�nr��tty �ṹָ�롣��73�к�벿������
// �������豸��dev��tty_table[]����ѡ���Ӧ��tty�ṹ�����dev = 0����ʾ����ʹ��
// ǰ̨�նˣ����ֱ��ʹ���ն˺�fg_console ��Ϊ tty_table[] ������ȡ tty�ṹ�����
// dev����0����ô��Ҫ������������ǣ��� dev �������ն˺ţ��� dev �Ǵ����ն˺Ż���
// α�ն˺š����������ն���tty�ṹ�� tty_table[]���������� dev-1��0 -- 63��������
// ���������նˣ������ǵ� tty�ṹ��������� dev�����磬���dev = 64����ʾ��һ����
// ���ն�1������tty �ṹ���� ttb_table[dev]�� ���dev = 1�����Ӧ�ն˵�tty�ṹ��
// tty_table[0]���μ�tty_io.c�����70 -- 73�С�
72 #define TTY_TABLE(nr) \
73 (tty_table + ((nr) ? (((nr) < 64)? (nr)-1:(nr)) : fg_console))
74
// ����������ն�termios�ṹ�пɸ��ĵ������ַ�����c_cc[]�ij�ʼֵ����termios�ṹ
// ������include/termios.h�С�POSIX.1������11�������ַ�������Linuxϵͳ�����ⶨ
// ����SVR4ʹ�õ�6�������ַ������������_POSIX_VDISABLE��\0������ô��ijһ��ֵ��
// ��_POSIX_VDISABLE��ֵʱ����ʾ��ֹʹ����Ӧ�������ַ���[8����ֵ]
75 /* intr=^C quit=^| erase=del kill=^U
76 eof=^D vtime=\0 vmin=\1 sxtc=\0
77 start=^Q stop=^S susp=^Z eol=\0
78 reprint=^R discard=^U werase=^W lnext=^V
79 eol2=\0
80 */
/* �ж�intr=^C �˳�quit=^| ɾ��erase=del ��ֹkill=^U
* �����eof=^D vtime=\0 vmin=\1 sxtc=\0
* ��ʼstart=^Q ֹͣstop=^S ����susp=^Z �н���eol=\0
* ����reprint=^R ����discard=^U werase=^W lnext=^V
* ���eol2=\0
*/
81 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
82
83 void rs_init(void); // �첽����ͨ�ų�ʼ����(kernel/chr_drv/serial.c)
84 void con_init(void); // �����ն˳�ʼ���� (kernel/chr_drv/console.c)
85 void tty_init(void); // tty��ʼ���� (kernel/chr_drv/tty_io.c)
86
87 int tty_read(unsigned c, char * buf, int n); // (kernel/chr_drv/tty_io.c)
88 int tty_write(unsigned c, char * buf, int n); // (kernel/chr_drv/tty_io.c)
89
90 void con_write(struct tty_struct * tty); // (kernel/chr_drv/console.c)
91 void rs_write(struct tty_struct * tty); // (kernel/chr_drv/serial.c)
92 void mpty_write(struct tty_struct * tty); // (kernel/chr_drv/pty.c)
93 void spty_write(struct tty_struct * tty); // (kernel/chr_drv/pty.c)
94
95 void copy_to_cooked(struct tty_struct * tty); // (kernel/chr_drv/tty_io.c)
96
97 void update_screen(void); // (kernel/chr_drv/console.c)
98
99 #endif
100
1 #ifndef _SYS_PARAM_H
2 #define _SYS_PARAM_H
3
4 #define HZ 100 // ϵͳʱ��Ƶ�ʣ�ÿ���ж�100�Ρ�
5 #define EXEC_PAGESIZE 4096 // ҳ���С��
6
7 #define NGROUPS 32 /* Max number of groups per user */ /* ÿ������������*/
8 #define NOGROUP -1
9
10 #define MAXHOSTNAMELEN 8 // ��������ȣ�8�ֽڡ�
11
12 #endif
13
1 /*
2 * Resource control/accounting header file for linux
3 */
/*
* Linux��Դ����/���ͷ�ļ���
4
5 #ifndef _SYS_RESOURCE_H
6 #define _SYS_RESOURCE_H
7
// ���·��ų����ͽṹ����getrusage()���μ�kernel/sys.c�ļ���412�п�ʼ��
8 /*
9 * Definition of struct rusage taken from BSD 4.3 Reno
10 *
11 * We don't support all of these yet, but we might as well have them....
12 * Otherwise, each time we add new items, programs which depend on this
13 * structure will lose. This reduces the chances of that happening.
14 */
/*
* rusage�ṹ�Ķ���ȡ��BSD 4.3 Renoϵͳ��
*
* �������ڻ�û��֧�ָýṹ�е�������Щ�ֶΣ������ǿ��ܻ�֧�����ǵ�....
* ����Ļ���ÿ�����������µ��ֶΣ���Щ����������ṹ�ij���ͻ�����⡣
* ���ڰ������ֶζ����������Ϳ��Ա����������鷢����
*/
// ������getrusage()�IJ���who��ʹ�õķ��ų�����
15 #define RUSAGE_SELF 0 // ���ص�ǰ���̵���Դ������Ϣ��
16 #define RUSAGE_CHILDREN -1 // ���ص�ǰ��������ֹ�͵ȴ��ŵ��ӽ��̵���Դ������Ϣ��
17
// rusage�ǽ��̵���Դ����ͳ�ƽṹ������getrusage()����ָ�����̶���Դ���õ�ͳ��ֵ��
// Linux 0.12�ں˽�ʹ����ǰ�����ֶΣ����Ƕ���timeval�ṹ��include/sys/time.h����
// ru_utime �C �������û�̬����ʱ��ͳ��ֵ��ru_stime �C �������ں�̬����ʱ��ͳ��ֵ��
18 struct rusage {
19 struct timeval ru_utime; /* user time used */
20 struct timeval ru_stime; /* system time used */
21 long ru_maxrss; /* maximum resident set size */
22 long ru_ixrss; /* integral shared memory size */
23 long ru_idrss; /* integral unshared data size */
24 long ru_isrss; /* integral unshared stack size */
25 long ru_minflt; /* page reclaims */
26 long ru_majflt; /* page faults */
27 long ru_nswap; /* swaps */
28 long ru_inblock; /* block input operations */
29 long ru_oublock; /* block output operations */
30 long ru_msgsnd; /* messages sent */
31 long ru_msgrcv; /* messages received */
32 long ru_nsignals; /* signals received */
33 long ru_nvcsw; /* voluntary context switches */
34 long ru_nivcsw; /* involuntary " */
35 };
36
// ������getrlimit()��setrlimit()ʹ�õķ��ų����ͽṹ��
37 /*
38 * Resource limits
39 */
/*
* ��Դ���ơ�
*/
// ������Linux 0.12�ں������������Դ���࣬��getrlimit()��setrlimit()�е�1������
// resource ��ȡֵ��Χ�� ��ʵ��Щ���ų������ǽ�������ṹ�� rlim[] �����������ֵ��
// rlim[]�����ÿһ���һ��rlimit�ṹ���ýṹ�������58�С�
40
41 #define RLIMIT_CPU 0 /* CPU time in ms */ /* ʹ�õ�CPUʱ�� */
42 #define RLIMIT_FSIZE 1 /* Maximum filesize */ /* �������� */
43 #define RLIMIT_DATA 2 /* max data size */ /* ������ݳ��� */
44 #define RLIMIT_STACK 3 /* max stack size */ /* ���ջ���� */
45 #define RLIMIT_CORE 4 /* max core file size */ /* ���core����� */
46 #define RLIMIT_RSS 5 /* max resident set size */ /* ���פ������С */
47
// ��������˷���notdef����Ҳ�������·��ų������塣
48 #ifdef notdef
49 #define RLIMIT_MEMLOCK 6 /* max locked-in-memory address space*/ /* ������ */
50 #define RLIMIT_NPROC 7 /* max number of processes */ /* ����ӽ����� */
51 #define RLIMIT_OFILE 8 /* max number of open files */ /* ������� */
52 #endif
53
// ������ų���������Linux�����Ƶ���Դ���ࡣRLIM_NLIMITS=6����˽�ǰ��6����Ч��
54 #define RLIM_NLIMITS 6
55
// ��ʾ��Դ���ޣ������ġ�
56 #define RLIM_INFINITY 0x7fffffff
57
// ��Դ���ṹ��
58 struct rlimit {
59 int rlim_cur; // ��ǰ��Դ���ƣ���������ƣ�soft limit����
60 int rlim_max; // Ӳ���ƣ�hard limit����
61 };
62
63 #endif /* _SYS_RESOURCE_H */
64
1 #ifndef _SYS_STAT_H
2 #define _SYS_STAT_H
3
4 #include <sys/types.h>
5
6 struct stat {
7 dev_t st_dev; // �����ļ����豸�š�
8 ino_t st_ino; // �ļ�i�ڵ�š�
9 umode_t st_mode; // �ļ����ͺ����ԣ������棩��
10 nlink_t st_nlink; // ָ���ļ�����������
11 uid_t st_uid; // �ļ����û�(��ʶ)�š�
12 gid_t st_gid; // �ļ�����š�
13 dev_t st_rdev; // �豸��(����ļ���������ַ��ļ�����ļ�)��
14 off_t st_size; // �ļ���С���ֽ�����������ļ��dz����ļ�����
15 time_t st_atime; // �ϴΣ������ʱ�䡣
16 time_t st_mtime; // �����ʱ�䡣
17 time_t st_ctime; // ���ڵ���ʱ�䡣
18 };
19
//
// ������Ϊst_mode�ֶ����õ�ֵ����ķ������ơ���Щֵ���ð˽��Ʊ�ʾ���μ���12���ļ�
// ϵͳ��ͼ12-5��i�ڵ������ֶ����ݣ��� Ϊ���ڼ��䣬��Щ�������ƾ�ΪһЩӢ�ĵ��ʵ���
// ��ĸ����д��϶��ɡ� �������� S_IFMT ��ÿ����ĸ�ֱ�������� State��Inode��File��
// Mask��Type�������� S_IFREG ����State��Inode��File��REGular������д��ĸ����ϣ�
// ����S_IRWXU��State��Inode��Read��Write��eXecute��User����ϡ��������ƿ��Դ����ơ�
// �ļ����ͣ�
20 #define S_IFMT 00170000 // �ļ����ͱ���λ�����루8���Ʊ�ʾ����
21 #define S_IFLNK 0120000 // �������ӡ�
22 #define S_IFREG 0100000 // �������
23 #define S_IFBLK 0060000 // �����⣨�豸���ļ��������dev/fd0��
24 #define S_IFDIR 0040000 // Ŀ¼��
25 #define S_IFCHR 0020000 // �ַ��豸�ļ���
26 #define S_IFIFO 0010000 // FIFO�������
// �ļ�����λ��
// S_ISUID���ڲ����ļ���set-user-ID��־�Ƿ���λ�����ñ�־��λ����ִ�и��ļ�ʱ�����̵�
// ��Ч�û�ID��������Ϊ���ļ��������û�ID��S_ISGID���������ID������ͬ������
27 #define S_ISUID 0004000 // ִ��ʱ�����û�ID��set-user-ID����
28 #define S_ISGID 0002000 // ִ��ʱ������ID��set-group-ID����
29 #define S_ISVTX 0001000 // ����Ŀ¼������ɾ����־��
30
31 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) // �����Ƿ���������ļ���
32 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) // �����Ƿ��ļ���
33 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) // �Ƿ�Ŀ¼�ļ���
34 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) // �Ƿ��ַ��豸�ļ���
35 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) // �Ƿ���豸�ļ���
36 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) // �Ƿ�FIFO�����ļ���
37
// �ļ�����Ȩ�ޣ�
38 #define S_IRWXU 00700 // �������Զ���д��ִ��/���������������ĸ����User����
39 #define S_IRUSR 00400 // ���������ɡ�
40 #define S_IWUSR 00200 // ����д���ɡ�
41 #define S_IXUSR 00100 // ����ִ��/�������ɡ�
42
43 #define S_IRWXG 00070 // ���Ա���Զ���д��ִ��/���������������ĸ����Group����
44 #define S_IRGRP 00040 // ���Ա�����ɡ�
45 #define S_IWGRP 00020 // ���Աд���ɡ�
46 #define S_IXGRP 00010 // ���Աִ��/�������ɡ�
47
48 #define S_IRWXO 00007 // �����˶���д��ִ��/�������ɣ����������ĸO����Other����
49 #define S_IROTH 00004 // �����˶����ɣ����3����ĸ����Other����
50 #define S_IWOTH 00002 // ������д���ɡ�
51 #define S_IXOTH 00001 // ������ִ��/�������ɡ�
52
53 extern int chmod(const char *_path, mode_t mode); // ���ļ����ԡ�
54 extern int fstat(int fildes, struct stat *stat_buf); // ȡָ���ļ�������ļ�״̬��Ϣ��
55 extern int mkdir(const char *_path, mode_t mode); // ����Ŀ¼��
56 extern int mkfifo(const char *_path, mode_t mode); // �����ܵ��ļ���
57 extern int stat(const char *filename, struct stat *stat_buf); // ȡָ���ļ������ļ�״̬��Ϣ��
58 extern mode_t umask(mode_t mask); // �������������롣
59
60 #endif
61
1 #ifndef _SYS_TIME_H
2 #define _SYS_TIME_H
3
4 /* gettimofday returns this */ // gettimeofday()�������ظ�ʱ��ṹ��
5 struct timeval {
6 long tv_sec; /* seconds */ // �롣
7 long tv_usec; /* microseconds */ // �롣
8 };
9
// ʱ�����ṹ��tzΪʱ����Time Zone������д��DST��Daylight Saving Time��������ʱ����д��
10 struct timezone {
11 int tz_minuteswest; /* minutes west of Greenwich */ // ����������������ʱ�䡣
12 int tz_dsttime; /* type of dst correction */ // ����ʱ������ʱ�䡣
13 };
14
15 #define DST_NONE 0 /* not on dst */ // ������ʱ��
16 #define DST_USA 1 /* USA style dst */ // USA��ʽ������ʱ��
17 #define DST_AUST 2 /* Australian style dst */ // ������ʽ������ʱ��
18 #define DST_WET 3 /* Western European dst */
19 #define DST_MET 4 /* Middle European dst */
20 #define DST_EET 5 /* Eastern European dst */
21 #define DST_CAN 6 /* Canada */
22 #define DST_GB 7 /* Great Britain and Eire */
23 #define DST_RUM 8 /* Rumania */
24 #define DST_TUR 9 /* Turkey */
25 #define DST_AUSTALT 10 /* Australian style with shift in 1986 */
26
// �ļ��������������ú꣬����select()������
27 #define FD_SET(fd,fdsetp) (*(fdsetp) |= (1 << (fd)))
28 #define FD_CLR(fd,fdsetp) (*(fdsetp) &= ~(1 << (fd)))
29 #define FD_ISSET(fd,fdsetp) ((*(fdsetp) >> fd) & 1)
30 #define FD_ZERO(fdsetp) (*(fdsetp) = 0)
31
32 /*
33 * Operations on timevals.
34 *
35 * NB: timercmp does not work for >= or <=.
36 */
// timevalʱ��ṹ�IJ���������
37 #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
38 #define timercmp(tvp, uvp, cmp) \
39 ((tvp)->tv_sec cmp (uvp)->tv_sec || \
40 (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
41 #define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
42
43 /*
44 * Names of the interval timers, and structure
45 * defining a timer setting.
46 */
/* �ڲ���ʱ�����ƺͽṹ�����ڶ��嶨ʱ�����á� */
47 #define ITIMER_REAL 0 // ��ʵ��ʱ��ݼ���
48 #define ITIMER_VIRTUAL 1 // �Խ�������ʱ��ݼ���
49 #define ITIMER_PROF 2 // �Խ�������ʱ����ߵ�ϵͳ����ʱ�Խ���ʱ��ݼ���
50
// �ڲ�ʱ��ṹ������it��Internal Timer�����ڲ���ʱ������д��
51 struct itimerval {
52 struct timeval it_interval; /* timer interval */
53 struct timeval it_value; /* current value */
54 };
55
56 #include <time.h>
57 #include <sys/types.h>
58
59 int gettimeofday(struct timeval * tp, struct timezone * tz);
60 int select(int width, fd_set * readfds, fd_set * writefds,
61 fd_set * exceptfds, struct timeval * timeout);
62
63 #endif /*_SYS_TIME_H*/
64
1 #ifndef _TIMES_H
2 #define _TIMES_H
3
4 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
5
6 struct tms {
7 time_t tms_utime; // �û�ʹ�õ�CPUʱ�䡣
8 time_t tms_stime; // ϵͳ���ںˣ�CPUʱ�䡣
9 time_t tms_cutime; // ����ֹ���ӽ���ʹ�õ��û�CPUʱ�䡣
10 time_t tms_cstime; // ����ֹ���ӽ���ʹ�õ�ϵͳCPUʱ�䡣
11 };
12
13 extern time_t times(struct tms * tp);
14
15 #endif
16
1 #ifndef _SYS_TYPES_H
2 #define _SYS_TYPES_H
3
4 #ifndef _SIZE_T
5 #define _SIZE_T
6 typedef unsigned int size_t; // ���ڶ���Ĵ�С�����ȣ���
7 #endif
8
9 #ifndef _TIME_T
10 #define _TIME_T
11 typedef long time_t; // ����ʱ�䣨����ƣ���
12 #endif
13
14 #ifndef _PTRDIFF_T
15 #define _PTRDIFF_T
16 typedef long ptrdiff_t;
17 #endif
18
19 #ifndef NULL
20 #define NULL ((void *) 0)
21 #endif
22
23 typedef int pid_t; // ���ڽ��̺źͽ�����š�
24 typedef unsigned short uid_t; // �����û��ţ��û���ʶ�ţ���
25 typedef unsigned char gid_t; // ������š�
26 typedef unsigned short dev_t; // �����豸�š�
27 typedef unsigned short ino_t; // �����ļ����кš�
28 typedef unsigned short mode_t; // ����ijЩ�ļ����ԡ�
29 typedef unsigned short umode_t; //
30 typedef unsigned char nlink_t; // �������Ӽ�����
31 typedef int daddr_t;
32 typedef long off_t; // �����ļ����ȣ���С����
33 typedef unsigned char u_char; // �����ַ����͡�
34 typedef unsigned short ushort; // ���Ŷ��������͡�
35
36 typedef unsigned char cc_t;
37 typedef unsigned int speed_t;
38 typedef unsigned long tcflag_t;
39
40 typedef unsigned long fd_set; // �ļ�����������ÿ���ش���1����������
41
42 typedef struct { int quot,rem; } div_t; // ����DIV������
43 typedef struct { long quot,rem; } ldiv_t; // ���ڳ�DIV������
44
// �ļ�ϵͳ�����ṹ������ustat()��������������ֶ�δʹ�ã����Ƿ���NULLָ�롣
45 struct ustat {
46 daddr_t f_tfree; // ϵͳ�ܿ��п�����
47 ino_t f_tinode; // �ܿ���i�ڵ�����
48 char f_fname[6]; // �ļ�ϵͳ���ơ�
49 char f_fpack[6]; // �ļ�ϵͳѹ�����ơ�
50 };
51
52 #endif
53
1 #ifndef _SYS_UTSNAME_H
2 #define _SYS_UTSNAME_H
3
4 #include <sys/types.h> // ����ͷ�ļ��������˻�����ϵͳ�������͡�
5 #include <sys/param.h> // �ں˲����ļ���
5
6 struct utsname {
7 char sysname[9]; // ��ǰ����ϵͳ�����ơ�
8 char nodename[MAXHOSTNAMELEN+1]; // ��ʵ����ص������нڵ����ƣ��������ƣ���
9 char release[9]; // ������ϵͳʵ�ֵĵ�ǰ���м���
10 char version[9]; // ���η��еIJ���ϵͳ�汾����
11 char machine[9]; // ϵͳ���е�Ӳ���������ơ�
12 };
13
14 extern int uname(struct utsname * utsbuf);
15
16 #endif
17
1 #ifndef _SYS_WAIT_H
2 #define _SYS_WAIT_H
3
4 #include <sys/types.h>
5
6 #define _LOW(v) ( (v) & 0377) // ȡ���ֽڣ�8���Ʊ�ʾ����
7 #define _HIGH(v) ( ((v) >> 8) & 0377) // ȡ���ֽڡ�
8
9 /* options for waitpid, WUNTRACED not supported */
/* waitpid��ѡ�����WUNTRACEDδ��֧�� */
// [ ע����ʵ0.12�ں��Ѿ�֧��WUNTRACEDѡ���������ע��Ӧ������ǰ�ں˰汾���������ġ� ]
// ���³��������Ǻ���waitpid(pid_t pid, long *stat_addr, int options)��optionsʹ�õ�ѡ�
10 #define WNOHANG 1 // ���û��״̬Ҳ��Ҫ���𣬲����̷��ء�
11 #define WUNTRACED 2 // ����ִֹͣ�е��ӽ���״̬��
12
// ���º궨�������ж�waitpid()�������ص�״̬�֣���20��21�еIJ���*stat_loc���ĺ��塣
13 #define WIFEXITED(s) (!((s)&0xFF) // ����ӽ��������˳�����Ϊ�档
14 #define WIFSTOPPED(s) (((s)&0xFF)==0x7F) // ����ӽ�����ֹͣ�ţ���Ϊtrue��
15 #define WEXITSTATUS(s) (((s)>>8)&0xFF) // �����˳�״̬��
16 #define WTERMSIG(s) ((s)&0x7F) // ���ص��½�����ֹ���ź�ֵ���ź�������
17 #define WCOREDUMP(s) ((s)&0x80) // �жϽ����Ƿ�ִ�����ڴ�ӳ��ת����dumpcore����
18 #define WSTOPSIG(s) (((s)>>8)&0xFF) // ���ص��½���ֹͣ���ź�ֵ��
19 #define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF) // �������δ���źŶ�
// �����ӽ����˳���Ϊ�档
20
// wait()��waitpit()�����������̻�ȡ�����ӽ���֮һ��״̬��Ϣ������ѡ��������ȡ�Ѿ���ֹ��
// ֹͣ���ӽ���״̬��Ϣ������������������������ӽ��̵�״̬��Ϣ�����˳���Dz�ָ���ġ�
// wait()������ǰ���̣�ֱ�����ӽ���֮һ�˳�����ֹ���������յ�Ҫ����ֹ�ý��̵��źţ�
// ��������Ҫ����һ���źž�����źŴ�������
// waitpid()����ǰ���̣�ֱ��pidָ�����ӽ����˳�����ֹ�������յ�Ҫ����ֹ�ý��̵��źţ�
// ��������Ҫ����һ���źž�����źŴ�������
// ���pid= -1��options=0����waitpid()��������wait()����һ������������Ϊ����pid��options
// �����IJ�ͬ����ͬ�����μ�kernel/exit.c,142��
// ����pid�ǽ��̺ţ�*stat_loc�DZ���״̬��Ϣλ�õ�ָ�룻options�ǵȴ�ѡ�����10��11�С�
21 pid_t wait(int *stat_loc);
22 pid_t waitpid(pid_t pid, int *stat_loc, int options);
23
24 #endif
25
1 /*
2 * linux/lib/_exit.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__ // ����һ�����ų�����������˵����
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// ��������__LIBRARY__����ϵͳ���úź���Ƕ���syscall0()�ȡ�
9
//// �ں�ʹ�õij���(�˳�)��ֹ������
// ֱ�ӵ���ϵͳ�ж�int 0x80�����ܺ�__NR_exit��
// ������exit_code - �˳��롣
// ������ǰ�Ĺؼ���volatile���ڸ��߱�����gcc�ú������᷵�ء���������gcc��������һ
// Щ�Ĵ��룬����Ҫ����ʹ������ؼ��ֿ��Ա������ijЩ��δ��ʼ�������ģ��پ�����Ϣ��
// ��ͬ��gcc�ĺ�������˵����void do_exit(int error_code) __attribute__ ((noreturn));
10 volatile void _exit(int exit_code)
11 {
// %0 - eax(ϵͳ���ú�__NR_exit)��%1 - ebx(�˳���exit_code)��
12 __asm__("int $0x80"::"a" (__NR_exit),"b" (exit_code));
13 }
14
1 /*
2 * linux/lib/close.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���syscall0()�ȡ�
9
// �ر��ļ�������
// ����õ��ú꺯����Ӧ��int close(int fd)��ֱ�ӵ�����ϵͳ�ж�int 0x80��������__NR_close��
// ����fd�����������
10 _syscall1(int,close,int,fd)
11
1 /*
2 * linux/lib/ctype.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <ctype.h> // �ַ�����ͷ�ļ���������һЩ�й��ַ������жϺ�ת���ĺꡣ
8
9 char _ctmp; // һ����ʱ�ַ���������ctype.h�ļ���ת���ַ��꺯��ʹ�á�
// �ַ���������(��)�������˸����ַ���Ӧ�����ԣ���Щ��������(��_C��)��ctype.h�ж��塣
// �����ж��ַ��ǿ����ַ�(_C)����д�ַ�(_U)��Сд�ַ�(_L)���������͡�
10 unsigned char _ctype[] = {0x00, /* EOF */
11 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
12 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
13 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
14 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
15 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
16 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
17 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
18 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
19 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
20 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
21 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
22 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
23 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
24 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
25 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
26 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
27 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
28 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
29 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */
30 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */
31 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */
32 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */
33 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */
34 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */
35
36
1 /*
2 * linux/lib/dup.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9
//// �����������������
// ����õ��ú꺯����Ӧ��int dup(int fd)��ֱ�ӵ�����ϵͳ�ж�int 0x80��������__NR_dup��
// ����fd�����������
10 _syscall1(int,dup,int,fd)
11
1 /*
2 * linux/lib/errno.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 int errno;
8
1 /*
2 * linux/lib/execve.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9
//// ���ز�ִ���ӽ���(��������)������
// ����õ��ú꺯����Ӧ��int execve(const char * file, char ** argv, char ** envp)��
// ������file - ��ִ�г����ļ�����argv - �����в���ָ�����飻envp - ��������ָ�����顣
// ֱ�ӵ�����ϵͳ�ж�int 0x80��������__NR_execve���μ�include/unistd.h��fs/exec.c����
10 _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
11
1 /*
2 * malloc.c --- a general purpose kernel memory allocator for Linux.
3 *
4 * Written by Theodore Ts'o (tytso@mit.edu), 11/29/91
5 *
6 * This routine is written to be as fast as possible, so that it
7 * can be called from the interrupt level.
8 *
9 * Limitations: maximum size of memory we can allocate using this routine
10 * is 4k, the size of a page in Linux.
11 *
12 * The general game plan is that each page (called a bucket) will only hold
13 * objects of a given size. When all of the object on a page are released,
14 * the page can be returned to the general free pool. When malloc() is
15 * called, it looks for the smallest bucket size which will fulfill its
16 * request, and allocate a piece of memory from that bucket pool.
17 *
18 * Each bucket has as its control block a bucket descriptor which keeps
19 * track of how many objects are in use on that page, and the free list
20 * for that page. Like the buckets themselves, bucket descriptors are
21 * stored on pages requested from get_free_page(). However, unlike buckets,
22 * pages devoted to bucket descriptor pages are never released back to the
23 * system. Fortunately, a system should probably only need 1 or 2 bucket
24 * descriptor pages, since a page can hold 256 bucket descriptors (which
25 * corresponds to 1 megabyte worth of bucket pages.) If the kernel is using
26 * that much allocated memory, it's probably doing something wrong. :-)
27 *
28 * Note: malloc() and free() both call get_free_page() and free_page()
29 * in sections of code where interrupts are turned off, to allow
30 * malloc() and free() to be safely called from an interrupt routine.
31 * (We will probably need this functionality when networking code,
32 * particularily things like NFS, is added to Linux.) However, this
33 * presumes that get_free_page() and free_page() are interrupt-level
34 * safe, which they may not be once paging is added. If this is the
35 * case, we will need to modify malloc() to keep a few unused pages
36 * "pre-allocated" so that it can safely draw upon those pages if
37 * it is called from an interrupt routine.
38 *
39 * Another concern is that get_free_page() should not sleep; if it
40 * does, the code is carefully ordered so as to avoid any race
41 * conditions. The catch is that if malloc() is called re-entrantly,
42 * there is a chance that unecessary pages will be grabbed from the
43 * system. Except for the pages for the bucket descriptor page, the
44 * extra pages will eventually get released back to the system, though,
45 * so it isn't all that bad.
46 */
47
/*
* malloc.c - Linux��ͨ���ں��ڴ���亯����
*
* ��Theodore Ts'o���� (tytso@mit.edu), 11/29/91
*
* �ú�������д�ɾ����ܵؿ죬�Ӷ����Դ��жϲ���ô˺�����
*
* ���ƣ�ʹ�øú���һ�����ܷ��������ڴ���4k��Ҳ��Linux���ڴ�ҳ��Ĵ�С��
*
* ��д�ú�������ѭ��һ�������ÿҳ(����Ϊһ���洢Ͱ)��������Ҫ���ɶ���Ĵ�С��
* ��һҳ�ϵ����ж����ͷź�ҳ�Ϳ��Է���ͨ�ÿ����ڴ�ء���malloc()������
* ʱ������Ѱ������Ҫ�����С�Ĵ洢Ͱ�����Ӹô洢Ͱ�з���һ���ڴ档
*
* ÿ���洢Ͱ����һ����Ϊ������õĴ洢Ͱ�����������м�¼��ҳ�����ж��ٶ�������
* ʹ���Լ���ҳ�Ͽ����ڴ���б�������洢Ͱ����һ�����洢Ͱ������Ҳ�Ǵ洢��ʹ��
* get_free_page()���뵽��ҳ���ϵģ�������洢Ͱ��ͬ���ǣ�Ͱ��������ռ�õ�ҳ��
* �����ٻ��ͷŸ�ϵͳ�����˵���һ��ϵͳ��Լֻ��Ҫ1��2ҳ��Ͱ������ҳ�棬��Ϊһ
* ��ҳ����Դ��256��Ͱ������(��Ӧ1MB�ڴ�Ĵ洢Ͱҳ��)�����ϵͳΪͰ��������
* ���������ڴ棬��ô�϶�ϵͳʲô�ط���������J��
*
* ע�⣡malloc()��free()���߹ر����жϵĴ��벿�ֶ�������get_free_page()��
* free_page()��������ʹmalloc()��free()����ȫ�ر����жϳ����е���
* (��������룬������NFS�ȱ����뵽Linux��ʱ�Ϳ�����Ҫ���ֹ���)����ǰ
* ���Ǽ���get_free_page()��free_page()�ǿ���ȫ�����жϼ�������ʹ�õģ�
* ����һ�������˷�ҳ����֮��Ϳ��ܲ��ǰ�ȫ�ġ�������������������ô����
* ����Ҫ��malloc()����Ԥ�ȷ��䡱��ҳ���õ��ڴ棬���malloc()��free()
* �����жϳ����е���ʱ�Ϳ���ȫ��ʹ����Щҳ�档
*
* ������Ҫ���ǵ�����get_free_page()��Ӧ��˯�ߣ������˯�ߵĻ�����Ϊ�˷�ֹ
* �κξ���������������Ҫ��ϸ�ذ���˳�� �ؼ��������malloc()�ǿ��������
* �����õĻ�����ô�ͻ���ڲ���Ҫ��ҳ�汻��ϵͳ��ȡ�ߵĻ��ᡣ��������Ͱ����
* ����ҳ�棬��Щ�����ҳ�����ջ��ͷŸ�ϵͳ�����Բ�������������������á�
*/
48 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
49 #include <linux/mm.h> // �ڴ����ͷ�ļ�������ҳ���С�����һЩҳ���ͷź���ԭ�͡�
50 #include <asm/system.h> // ϵͳͷ�ļ������������û���������/�ж��ŵȵ�Ƕ��ʽ���ꡣ
51
// �洢Ͱ�������ṹ��
52 struct bucket_desc { /* 16 bytes */
53 void *page; // ��Ͱ��������Ӧ���ڴ�ҳ��ָ�롣
54 struct bucket_desc *next; // ��һ��������ָ�롣
55 void *freeptr; // ָ��Ͱ�п����ڴ�λ�õ�ָ�롣
56 unsigned short refcnt; // ���ü�����
57 unsigned short bucket_size; // ����������Ӧ�洢Ͱ�Ĵ�С��
58 };
59
// �洢Ͱ������Ŀ¼�ṹ��
60 struct _bucket_dir { /* 8 bytes */
61 int size; // �ô洢Ͱ�Ĵ�С(�ֽ���)��
62 struct bucket_desc *chain; // �ô洢ͰĿ¼���Ͱ����������ָ�롣
63 };
64
65 /*
66 * The following is the where we store a pointer to the first bucket
67 * descriptor for a given size.
68 *
69 * If it turns out that the Linux kernel allocates a lot of objects of a
70 * specific size, then we may want to add that specific size to this list,
71 * since that will allow the memory to be allocated more efficiently.
72 * However, since an entire page must be dedicated to each specific size
73 * on this list, some amount of temperance must be exercised here.
74 *
75 * Note that this list *must* be kept in order.
76 */
/*
* ���������Ǵ�ŵ�һ��������С�洢Ͱ������ָ��ĵط���
*
* ���Linux�ں˷���������ָ����С�Ķ�����ô���Ǿ�ϣ������ָ���Ĵ�С�ӵ�
* ���б�(����)�У���Ϊ��������ʹ�ڴ�ķ������Ч�����ǣ���Ϊһҳ�����ڴ�ҳ��
* ���������б���ָ����С�����ж���������Ҫ����������IJ��Բ�����
*/
// �洢ͰĿ¼�б�(����)��
77 struct _bucket_dir bucket_dir[] = {
78 { 16, (struct bucket_desc *) 0}, // 16�ֽڳ��ȵ��ڴ�顣
79 { 32, (struct bucket_desc *) 0}, // 32�ֽڳ��ȵ��ڴ�顣
80 { 64, (struct bucket_desc *) 0}, // 64�ֽڳ��ȵ��ڴ�顣
81 { 128, (struct bucket_desc *) 0}, // 128�ֽڳ��ȵ��ڴ�顣
82 { 256, (struct bucket_desc *) 0}, // 256�ֽڳ��ȵ��ڴ�顣
83 { 512, (struct bucket_desc *) 0}, // 512�ֽڳ��ȵ��ڴ�顣
84 { 1024, (struct bucket_desc *) 0}, // 1024�ֽڳ��ȵ��ڴ�顣
85 { 2048, (struct bucket_desc *) 0}, // 2048�ֽڳ��ȵ��ڴ�顣
86 { 4096, (struct bucket_desc *) 0}, // 4096�ֽ�(1ҳ)�ڴ档
87 { 0, (struct bucket_desc *) 0}}; /* End of list marker */
88
89 /*
90 * This contains a linked list of free bucket descriptor blocks
91 */
/*
* �����Ǻ��п���Ͱ�������ڴ���������
*/
92 struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;
93
94 /*
95 * This routine initializes a bucket description page.
96 */
/*
* ������ӳ������ڳ�ʼ��һҳͰ������ҳ�档
*/
//// ��ʼ��Ͱ��������
// ��������Ͱ����������������free_bucket_descָ���һ������Ͱ��������
97 static inline void init_bucket_desc()
98 {
99 struct bucket_desc *bdesc, *first;
100 int i;
101
// ����һҳ�ڴ棬���ڴ��Ͱ�����������ʧ�ܣ�����ʾ��ʼ��Ͱ������ʱ�ڴ治��������Ϣ��������
102 first = bdesc = (struct bucket_desc *) get_free_page();
103 if (!bdesc)
104 panic("Out of memory in init_bucket_desc()");
// ���ȼ���һҳ�ڴ��пɴ�ŵ�Ͱ������������Ȼ����佨����������ָ�롣
105 for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {
106 bdesc->next = bdesc+1;
107 bdesc++;
108 }
109 /*
110 * This is done last, to avoid race conditions in case
111 * get_free_page() sleeps and this routine gets called again....
112 */
/*
* ������������ģ�Ŀ����Ϊ�˱�����get_free_page()˯��ʱ���ӳ����ֱ�
* ���ö�����ľ���������
*/
// ������Ͱ������ָ��free_bucket_desc���������С�
113 bdesc->next = free_bucket_desc;
114 free_bucket_desc = first;
115 }
116
//// ���䶯̬�ڴ溯����
// ������len - ������ڴ�鳤�ȡ�
// ���أ�ָ�����ڴ��ָ�롣���ʧ����NULL��
117 void *malloc(unsigned int len)
118 {
119 struct _bucket_dir *bdir;
120 struct bucket_desc *bdesc;
121 void *retval;
122
123 /*
124 * First we search the bucket_dir to find the right bucket change
125 * for this request.
126 */
/*
* �������������洢ͰĿ¼bucket_dir��Ѱ���ʺ������Ͱ��С��
*/
// �����洢ͰĿ¼��Ѱ���ʺ������ڴ���С��Ͱ���������������Ŀ¼���Ͱ�ֽ�������������ֽ�
// �������ҵ��˶�Ӧ��ͰĿ¼�
127 for (bdir = bucket_dir; bdir->size; bdir++)
128 if (bdir->size >= len)
129 break;
// �������������Ŀ¼��û���ҵ����ʴ�С��Ŀ¼��������������ڴ���С̫�����˸�
// ����ķ�������(�Ϊ1��ҳ��)��������ʾ������Ϣ��������
130 if (!bdir->size) {
131 printk("malloc called with impossibly large argument (%d)\n",
132 len);
133 panic("malloc: bad arg");
134 }
135 /*
136 * Now we search for a bucket descriptor which has free space
137 */
/*
* �����������������п��пռ��Ͱ��������
*/
138 cli(); /* Avoid race conditions */ /* Ϊ�˱�����־������������ȹ��ж� */
// ������ӦͰĿ¼�������������������Ҿ��п��пռ��Ͱ�����������Ͱ�������Ŀ����ڴ�ָ��
// freeptr��Ϊ�գ����ʾ�ҵ�����Ӧ��Ͱ��������
139 for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)
140 if (bdesc->freeptr)
141 break;
142 /*
143 * If we didn't find a bucket with free space, then we'll
144 * allocate a new one.
145 */
/*
* ���û���ҵ����п��пռ��Ͱ����������ô���Ǿ�Ҫ�½���һ����Ŀ¼�����������
*/
146 if (!bdesc) {
147 char *cp;
148 int i;
149
// ��free_bucket_desc��Ϊ��ʱ����ʾ��һ�ε��øó��������������п�Ͱ�������������ꡣ
// ��ʱ����Ҫ����һ��ҳ�沢�����Ͻ�������ʼ������������������free_bucket_desc��ָ���һ
// ������Ͱ��������
150 if (!free_bucket_desc)
151 init_bucket_desc();
// ȡfree_bucket_descָ��Ŀ���Ͱ������������free_bucket_descָ����һ������Ͱ��������
152 bdesc = free_bucket_desc;
153 free_bucket_desc = bdesc->next;
// ��ʼ�����µ�Ͱ������������������������0��Ͱ�Ĵ�С���ڶ�ӦͰĿ¼�Ĵ�С������һ�ڴ�ҳ�棬
// ����������ҳ��ָ��pageָ���ҳ�棻�����ڴ�ָ��Ҳָ���ҳ��ͷ����Ϊ��ʱȫΪ���С�
154 bdesc->refcnt = 0;
155 bdesc->bucket_size = bdir->size;
156 bdesc->page = bdesc->freeptr = (void *) cp = get_free_page();
// ��������ڴ�ҳ�����ʧ�ܣ�����ʾ������Ϣ��������
157 if (!cp)
158 panic("Out of memory in kernel malloc()");
159 /* Set up the chain of free objects */
/* �ڸ�ҳ�����ڴ��н������ж������� */
// �Ը�ͰĿ¼��ָ����Ͱ��СΪ���ȣ��Ը�ҳ�ڴ���л��֣���ʹÿ������Ŀ�ʼ4�ֽ�����
// ��ָ����һ�����ָ�롣
160 for (i=PAGE_SIZE/bdir->size; i > 1; i--) {
161 *((char **) cp) = cp + bdir->size;
162 cp += bdir->size;
163 }
// ���һ������ʼ����ָ������Ϊ0(NULL)��
// Ȼ���ø�Ͱ����������һ������ָ���ֶ�ָ���ӦͰĿ¼��ָ��chain��ָ������������ͰĿ¼��
// chainָ���Ͱ��������Ҳ���������������뵽����������ͷ����
164 *((char **) cp) = 0;
165 bdesc->next = bdir->chain; /* OK, link it in! */ /* OK���������룡*/
166 bdir->chain = bdesc;
167 }
// ����ָ�뼴���ڸ���������Ӧҳ��ĵ�ǰ����ָ�롣Ȼ������ÿ��пռ�ָ��ָ����һ�����ж���
// ��ʹ�������ж�Ӧҳ���ж������ü�����1��
168 retval = (void *) bdesc->freeptr;
169 bdesc->freeptr = *((void **) retval);
170 bdesc->refcnt++;
// ����жϣ�������ָ������ڴ�����ָ�롣
171 sti(); /* OK, we're safe again */ /* OK�����������ְ�ȫ��*/
172 return(retval);
173 }
174
175 /*
176 * Here is the free routine. If you know the size of the object that you
177 * are freeing, then free_s() will use that information to speed up the
178 * search for the bucket descriptor.
179 *
180 * We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"
181 */
/*
* �������ͷ��ӳ��������֪���ͷŶ���Ĵ�С����free_s()��ʹ�ø���Ϣ����
* ��Ѱ��ӦͰ���������ٶȡ�
*
* ���ǽ�����һ���꣬ʹ��"free(x)"��Ϊ"free_s(x, 0)"��
*/
//// �ͷŴ洢Ͱ����
// ������obj - ��Ӧ����ָ�룻size - ��С��
182 void free_s(void *obj, int size)
183 {
184 void *page;
185 struct _bucket_dir *bdir;
186 struct bucket_desc *bdesc, *prev;
187
188 /* Calculate what page this object lives in */
/* ����ö������ڵ�ҳ�� */
189 page = (void *) ((unsigned long) obj & 0xfffff000);
190 /* Now search the buckets looking for that page */
/* ���������洢ͰĿ¼�������ӵ�Ͱ��������Ѱ�Ҹ�ҳ�� */
//
191 for (bdir = bucket_dir; bdir->size; bdir++) {
192 prev = 0;
193 /* If size is zero then this conditional is always false */
/* �������size��0�������������϶���false */
194 if (bdir->size < size)
195 continue;
// ������ӦĿ¼�������ӵ����������������Ҷ�Ӧҳ�档���ij������ҳ��ָ�����page���ʾ�ҵ�
// ����Ӧ������������ת��found����������������ж�Ӧpage������������ָ��prevָ�����������
196 for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
197 if (bdesc->page == page)
198 goto found;
199 prev = bdesc;
200 }
201 }
// �������˶�ӦĿ¼���������������û���ҵ�ָ����ҳ�棬����ʾ������Ϣ��������
202 panic("Bad address passed to kernel free_s()");
203 found:
// �ҵ���Ӧ��Ͱ�����������ȹ��жϡ�Ȼ�ö����ڴ��������п���������У���ʹ��������
// �Ķ������ü�����1��
204 cli(); /* To avoid race conditions */ /* Ϊ�˱��⾺������ */
205 *((void **)obj) = bdesc->freeptr;
206 bdesc->freeptr = obj;
207 bdesc->refcnt--;
// ������ü����ѵ���0�������ǾͿ����ͷŶ�Ӧ���ڴ�ҳ���Ͱ��������
208 if (bdesc->refcnt == 0) {
209 /*
210 * We need to make sure that prev is still accurate. It
211 * may not be, if someone rudely interrupted us....
212 */
/*
* ������Ҫȷ��prev��Ȼ����ȷ�ģ���ij�����³���ж�������
* ���п��ܲ����ˡ�
*/
// ���prev�Ѿ���������������������ǰһ����������������������ǰ��������ǰһ����������
213 if ((prev && (prev->next != bdesc)) ||
214 (!prev && (bdir->chain != bdesc)))
215 for (prev = bdir->chain; prev; prev = prev->next)
216 if (prev->next == bdesc)
217 break;
// ����ҵ���ǰһ�����������������������ɾ����ǰ��������
218 if (prev)
219 prev->next = bdesc->next;
// ���prev==NULL����˵����ǰһ���������Ǹ�Ŀ¼������������Ҳ��Ŀ¼����chainӦ��ֱ��
// ָ��ǰ������bdesc�������ʾ���������⣬����ʾ������Ϣ����������ˣ�Ϊ�˽���ǰ������
// ��������ɾ����Ӧ����chainָ����һ����������
220 else {
221 if (bdir->chain != bdesc)
222 panic("malloc bucket chains corrupted");
223 bdir->chain = bdesc->next;
224 }
// �ͷŵ�ǰ���������������ڴ�ҳ�棬�������������������������������ʼ����
225 free_page((unsigned long) bdesc->page);
226 bdesc->next = free_bucket_desc;
227 free_bucket_desc = bdesc;
228 }
// ���жϣ����ء�
229 sti();
230 return;
231 }
232
233
1 /*
2 * linux/lib/open.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9 #include <stdarg.h> // ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��
// ����(va_list)��������(va_start, va_arg��va_end)������
// vsprintf��vprintf��vfprintf������
10
//// ���������
// ���п��ܴ���һ���ļ���
// ������filename - �ļ�����flag - �ļ���־��...
// ���أ��ļ������������������ó����룬������-1��
// ��13�ж�����һ���Ĵ�������res���ñ�������������һ���Ĵ����У��Ա��ڸ�Ч���ʺͲ�����
// ����ָ����ŵļĴ���������eax������ô���Ѹþ�д����register int res asm("ax");����
11 int open(const char * filename, int flag, ...)
12 {
13 register int res;
14 va_list arg;
15
// ����va_start()�꺯����ȡ��flag���������ָ�룬Ȼ�����ϵͳ�ж�int 0x80������open����
// �������
// %0 - eax(���ص��������������)��%1 - eax(ϵͳ�жϵ��ù��ܺ�__NR_open)��
// %2 - ebx(�ļ���filename)��%3 - ecx(���ļ���־flag)��%4 - edx(��������ļ�����mode)��
16 va_start(arg,flag);
17 __asm__("int $0x80"
18 :"=a" (res)
19 :"" (__NR_open),"b" (filename),"c" (flag),
20 "d" (va_arg(arg,int)));
// ϵͳ�жϵ��÷���ֵ���ڻ����0����ʾ��һ���ļ�����������ֱ�ӷ���֮��
21 if (res>=0)
22 return res;
// ����˵������ֵС��0�������һ�������롣���øó����벢����-1��
23 errno = -res;
24 return -1;
25 }
26
1 /*
2 * linux/lib/setsid.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9
//// ����һ���Ự�����ý�����š�
// ����ϵͳ���ú��Ӧ�ں�����pid_t setsid()��
// ���أ����ý��̵ĻỰ��ʶ��(session ID)��
10 _syscall0(pid_t,setsid)
11
1 /*
2 * linux/lib/string.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #ifndef __GNUC__ // ��ҪGNU��C���������롣
8 #error I want gcc!
9 #endif
10
11 #define extern
12 #define inline
13 #define __LIBRARY__
14 #include <string.h>
15
1 /*
2 * linux/lib/wait.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9 #include <sys/wait.h> // �ȴ�����ͷ�ļ�������ϵͳ����wait()��waitpid()����س������š�
10
//// �ȴ�������ֹϵͳ���ú�����
// �������ṹ��Ӧ�ں�����pid_t waitpid(pid_t pid, int * wait_stat, int options)
//
// ������pid - �ȴ�����ֹ���̵Ľ���id������������ָ����������������ض���ֵ��
// wait_stat - ���ڴ��״̬��Ϣ��options - WNOHANG��WUNTRACED����0��
11 _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
12
//// wait()ϵͳ���á�ֱ�ӵ���waitpid()������
13 pid_t wait(int * wait_stat)
14 {
15 return waitpid(-1,wait_stat,0);
16 }
17
1 /*
2 * linux/lib/write.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #define __LIBRARY__
8 #include <unistd.h> // Linux��ͷ�ļ��������˸��ַ��ų��������ͣ��������˸��ֺ�����
// �綨����__LIBRARY__����ϵͳ���úź���Ƕ���_syscall0()�ȡ�
9
//// д�ļ�ϵͳ���ú�����
// �ú�ṹ��Ӧ�ں�����int write(int fd, const char * buf, off_t count)
// ������fd - �ļ���������buf - д������ָ�룻count - д�ֽ�����
// ���أ��ɹ�ʱ����д����ֽ���(0��ʾд��0�ֽ�)������ʱ������-1�����������˳����š�
10 _syscall3(int,write,int,fd,const char *,buf,off_t,count)
11
1 /*
2 * linux/tools/build.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * This file builds a disk-image from three different files:
9 *
10 * - bootsect: max 510 bytes of 8086 machine code, loads the rest
11 * - setup: max 4 sectors of 8086 machine code, sets up system parm
12 * - system: 80386 code for actual system
13 *
14 * It does some checking that all files are of the correct type, and
15 * just writes the result to stdout, removing headers and padding to
16 * the right amount. It also writes some system data to stderr.
17 */
/*
* �ó����������ͬ�ij����д�������ӳ���ļ���
*
* - bootsect�����ļ���8086�������Ϊ510�ֽڣ����ڼ�����������
* - setup�����ļ���8086�������Ϊ4��������������������ϵͳ������
* - system��ʵ��ϵͳ��80386���롣
*
* �ó������ȼ�����г���ģ��������Ƿ���ȷ��������������ն�����ʾ������
* Ȼ��ɾ��ģ��ͷ�����������ȷ�ij��ȡ��ó���Ҳ�ὫһЩϵͳ����д��stderr��
*/
18
19 /*
20 * Changes by tytso to allow root device specification
21 *
22 * Added swap-device specification: Linux 20.12.91
23 */
/*
* tytso�Ըó��������ģ�������ָ�����ļ��豸��
*
* ������ָ�������豸���ܣ�Linus 20.12.91
*/
24
25 #include <stdio.h> /* fprintf */ // ʹ�����е�fprintf()������
26 #include <string.h> // �ַ�������������
27 #include <stdlib.h> /* contains exit */ // ��exit����ԭ��˵����
28 #include <sys/types.h> /* unistd.h needs this */ // ��ͷ�ļ���unistd.h�ļ�ʹ�á�
29 #include <sys/stat.h> // ���ļ�״̬��Ϣ�ṹ���塣
30 #include <linux/fs.h> // �ļ�ϵͳͷ�ļ���
31 #include <unistd.h> /* contains read/write */ // ��read/write����ԭ��˵����
32 #include <fcntl.h> // �����ļ�����ģʽ���ų�����
33
34 #define MINIX_HEADER 32 // minix������Ŀ���ļ�ģ��ͷ������Ϊ32�ֽڡ�
35 #define GCC_HEADER 1024 // GCCͷ����Ϣ����Ϊ1024�ֽڡ�
36
37 #define SYS_SIZE 0x3000 // system�ļ������(�ֽ���ΪSYS_SIZE*16=128KB)��
38
// Ĭ�ϵذ�Linux���ļ�ϵͳ�����豸����Ϊ�ڵ�2��Ӳ�̵ĵ�1�������ϣ����豸��Ϊ0x0306����
// ����ΪLinus��ʱ����Linuxʱ���ѵ�1��Ӳ������MINIXϵͳ�̣�����2��Ӳ������ΪLinux
// �ĸ��ļ�ϵͳ�̡�
39 #define DEFAULT_MAJOR_ROOT 3 // Ĭ�ϸ��豸���豸�� - 3��Ӳ�̣���
40 #define DEFAULT_MINOR_ROOT 6 // Ĭ�ϸ��豸���豸�� - 6����2��Ӳ�̵ĵ�1��������
41
42 #define DEFAULT_MAJOR_SWAP 0 // Ĭ�Ͻ����豸���豸�š�
43 #define DEFAULT_MINOR_SWAP 0 // Ĭ�Ͻ����豸���豸�š�
44
45 /* max nr of sectors of setup: don't change unless you also change
46 * bootsect etc */
/* ����ָ��setupģ��ռ���������������Ҫ�ı��ֵ������Ҳ�ı�bootsect����Ӧ�ļ���
47 #define SETUP_SECTS 4 // setup���Ϊ4��������2KB����
48
49 #define STRINGIFY(x) #x // ��xת�����ַ������ͣ����ڳ�����ʾ����С�
50
//// ��ʾ������Ϣ������ֹ����
51 void die(char * str)
52 {
53 fprintf(stderr,"%s\n",str);
54 exit(1);
55 }
56
// ��ʾ����ʹ�÷��������˳���
57 void usage(void)
58 {
59 die("Usage: build bootsect setup system [rootdev] [> image]");
60 }
61
// ������ʼ��
62 int main(int argc, char ** argv)
63 {
64 int i,c,id;
65 char buf[1024];
66 char major_root, minor_root;
67 char major_swap, minor_swap;
68 struct stat sb;
69
// ���ȼ��build����ִ��ʱʵ�������в��������������ݲ�����������Ӧ���á����build����
// �����в�����������4��6��������������1����������ʾ�����÷����˳���
70 if ((argc < 4) || (argc > 6))
71 usage();
// ���������������ж���4����������ô������豸���������̣�"FLOPPY"������ȡ���豸�ļ���
// ״̬��Ϣ����ȡ״̬��������ʾ��Ϣ���˳�������ȡ���豸��״̬�ṹ�е����豸�źʹ��豸��
// ��Ϊ���豸�š�������豸����FLOPPY�豸���������豸�źʹ��豸��ȡ0����ʾ���豸�ǵ�ǰ
// ���������豸��
72 if (argc > 4) {
73 if (strcmp(argv[4], "FLOPPY")) {
74 if (stat(argv[4], &sb)) {
75 perror(argv[4]);
76 die("Couldn't stat root device.");
77 }
78 major_root = MAJOR(sb.st_rdev); // ȡ�豸��״̬�ṹ���豸�š�
79 minor_root = MINOR(sb.st_rdev);
80 } else {
81 major_root = 0;
82 minor_root = 0;
83 }
// ������ֻ��4�����������豸�źʹ��豸�ŵ���ϵͳĬ�ϵĸ��豸�š�
84 } else {
85 major_root = DEFAULT_MAJOR_ROOT;
86 minor_root = DEFAULT_MINOR_ROOT;
87 }
// ����������������6����������ô������һ����ʾ�����豸�IJ��������ޣ�"NONE"������ȡ��
// �豸�ļ���״̬��Ϣ����ȡ״̬��������ʾ��Ϣ���˳�������ȡ���豸��״̬�ṹ�е����豸��
// �ʹ��豸����Ϊ�����豸�š�������һ����������"NONE"�����ý����豸�����豸�źʹ��豸
// ��ȡΪ0����ʾ�����豸���ǵ�ǰ���������豸��
88 if (argc == 6) {
89 if (strcmp(argv[5], "NONE")) {
90 if (stat(argv[5], &sb)) {
91 perror(argv[5]);
92 die("Couldn't stat root device.");
93 }
94 major_swap = MAJOR(sb.st_rdev); // ȡ�豸��״̬�ṹ���豸�š�
95 minor_swap = MINOR(sb.st_rdev);
96 } else {
97 major_swap = 0;
98 minor_swap = 0;
99 }
// ������û��6������5������ʾ��������û�д������豸�������Ǿ��ý����豸���豸�źʹ��豸
// �ŵ���ϵͳĬ�ϵĽ����豸�š�
100 } else {
101 major_swap = DEFAULT_MAJOR_SWAP;
102 minor_swap = DEFAULT_MINOR_SWAP;
103 }
// �������ڱ������ն�����ʾ������ѡ��ĸ��豸�������豸�źͽ����豸�������豸�š����
// ���豸�Ų�����2�����̣���3��Ӳ�̣���Ҳ��Ϊ0��ȡϵͳĬ���豸��������ʾ������Ϣ���˳���
// �ն˵ı�����������ļ�Image����˱�������������ں˴������ݣ������ں�ӳ���ļ���
104 fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
105 fprintf(stderr, "Swap device is (%d, %d)\n", major_swap, minor_swap);
106 if ((major_root != 2) && (major_root != 3) &&
107 (major_root != 0)) {
108 fprintf(stderr, "Illegal root device (major = %d)\n",
109 major_root);
110 die("Bad root device --- major #");
111 }
112 if (major_swap && major_swap != 3) {
113 fprintf(stderr, "Illegal swap device (major = %d)\n",
114 major_swap);
115 die("Bad root device --- major #");
116 }
// ���濪ʼִ�ж�ȡ�����ļ����ݲ�������Ӧ�ĸ��ƴ��������ȳ�ʼ��1KB�ĸ��ƻ���������ȫ0��
// Ȼ����ֻ����ʽ����1ָ�����ļ���bootsect�������ж�ȡ32�ֽڵ�MINIXִ���ļ�ͷ�ṹ
// ���ݣ��μ��б���˵������������buf�С�
117 for (i=0;i<sizeof buf; i++) buf[i]=0;
118 if ((id=open(argv[1],O_RDONLY,0))<0)
119 die("Unable to open 'boot'");
120 if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
121 die("Unable to read header of 'boot'");
// ����������MINIXͷ���ṹ�ж�bootsect�Ƿ�Ϊһ����Ч��MINIXִ���ļ������ǣ�����ļ���
// ��ȡ512�ֽڵ�����������������ݡ�
// 0x0301 - MINIXͷ��a_magicħ����0x10 - a_flag��ִ�У�0x04 - a_cpu, Intel 8086�����롣
122 if (((long *) buf)[0]!=0x04100301)
123 die("Non-Minix header of 'boot'");
// �ж�ͷ�������ֶ�a_hdrlen���ֽڣ��Ƿ���ȷ��32�ֽڣ����������ֽ�����û���ã���0��
124 if (((long *) buf)[1]!=MINIX_HEADER)
125 die("Non-Minix header of 'boot'");
// �ж����ݶγ�a_data�ֶ�(long)�����Ƿ�Ϊ0��
126 if (((long *) buf)[3]!=0)
127 die("Illegal data segment in 'boot'");
// �ж϶�a_bss�ֶ�(long)�����Ƿ�Ϊ0��
128 if (((long *) buf)[4]!=0)
129 die("Illegal bss in 'boot'");
// �ж�ִ�е�a_entry�ֶ�(long)�����Ƿ�Ϊ0��
130 if (((long *) buf)[5] != 0)
131 die("Non-Minix header of 'boot'");
// �жϷ��ű����ֶ�a_sym�������Ƿ�Ϊ0��
132 if (((long *) buf)[7] != 0)
133 die("Illegal symbol table in 'boot'");
// �������ж϶���ȷ�������¶�ȡ�ļ�������ʵ�ʴ������ݣ�Ӧ�÷��ض�ȡ�ֽ���Ϊ512�ֽڡ�
// ��Ϊbootsect�ļ��а�������1������������������������ݣ��������2�ֽ�Ӧ���ǿ�����
// ��־0xAA55��
134 i=read(id,buf,sizeof buf);
135 fprintf(stderr,"Boot sector %d bytes.\n",i);
136 if (i != 512)
137 die("Boot block must be exactly 512 bytes");
138 if ((*(unsigned short *)(buf+510)) != 0xAA55)
139 die("Boot block hasn't got boot flag (0xAA55)");
// ����������506��507ƫ�ƴ����Ž����豸�ţ�508��509ƫ�ƴ����Ÿ��豸�š�
140 buf[506] = (char) minor_swap;
141 buf[507] = (char) major_swap;
142 buf[508] = (char) minor_root;
143 buf[509] = (char) major_root;
// Ȼ��512�ֽڵ�����д�������stdout����д���ֽ������ԣ�����ʾ������Ϣ���˳���
// ��linux/Makefile�У�build�����������ض����ں�ӳ���ļ���Image�ϣ��������
// ������������ݻᱻд��Image��ʼ��512�ֽڴ������ر�bootsectģ���ļ���
144 i=write(1,buf,512);
145 if (i!=512)
146 die("Write call failed");
147 close (id);
148
// ������ֻ����ʽ����2ָ�����ļ���setup�������ж�ȡ32�ֽڵ�MINIXִ���ļ�ͷ�ṹ
// ���ݵ�������buf�С�������ʽ��������ͬ��������ֻ����ʽ��ָ�����ļ�setup�����ж�
// ȡ32�ֽڵ�MINIXִ���ļ�ͷ�ṹ���ݵ�������buf�С�
149 if ((id=open(argv[2],O_RDONLY,0))<0)
150 die("Unable to open 'setup'");
151 if (read(id,buf,MINIX_HEADER) != MINIX_HEADER)
152 die("Unable to read header of 'setup'");
// ����������MINIXͷ���ṹ�ж�setup�Ƿ�Ϊһ����Ч��MINIXִ���ļ������ǣ�����ļ���
// ��ȡ512�ֽڵ�����������������ݡ�
// 0x0301- MINIXͷ��a_magicħ����0x10- a_flag��ִ�У�0x04- a_cpu, Intel 8086�����롣
153 if (((long *) buf)[0]!=0x04100301)
154 die("Non-Minix header of 'setup'");
// �ж�ͷ�������ֶ�a_hdrlen���ֽڣ��Ƿ���ȷ��32�ֽڣ����������ֽ�����û���ã���0��
155 if (((long *) buf)[1]!=MINIX_HEADER)
156 die("Non-Minix header of 'setup'");
// �ж����ݶγ��ֶ�a_data�����ֶ�a_bss����ʼִ�е��ֶ�a_entry�ͷ��ű��ֶ�a_sym������
// �Ƿ�Ϊ0�����붼Ϊ0��
157 if (((long *) buf)[3]!=0) // ���ݶγ�a_data�ֶΡ�
158 die("Illegal data segment in 'setup'");
159 if (((long *) buf)[4]!=0) // ��a_bss�ֶΡ�
160 die("Illegal bss in 'setup'");
161 if (((long *) buf)[5] != 0) // ִ����ʼ��a_entry�ֶΡ�
162 die("Non-Minix header of 'setup'");
163 if (((long *) buf)[7] != 0)
164 die("Illegal symbol table in 'setup'");
// �������ж϶���ȷ�������¶�ȡ�ļ�������ʵ�ʴ������ݣ�����д���ն˱������ͬʱͳ��
// д�ij��ȣ�i�������ڲ���������ر�setup�ļ���֮���ж�һ������setupִ��д�����Ĵ���
// �����ݳ���ֵ����ֵ���ܴ���(SETUP_SECTS * 512)�ֽڣ�����͵�������build��bootsect
// ��setup�������趨��setup��ռ�����������±����ںˡ���һ����������ʾsetupʵ�ʳ���ֵ��
165 for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
166 if (write(1,buf,c)!=c)
167 die("Write call failed");
168 close (id); //�ر�setupģ���ļ���
169 if (i > SETUP_SECTS*512)
170 die("Setup exceeds " STRINGIFY(SETUP_SECTS)
171 " sectors - rewrite build/boot/setup");
172 fprintf(stderr,"Setup is %d bytes.\n",i);
// �ڽ�������buf����֮���ж�ʵ��д��setup������(SETUP_SECTS4*512)����ֵ���setup
// ����С�ڸó��ȣ�4*512�ֽڣ�������NULL�ַ���setup����Ϊ4*512�ֽڡ�
173 for (c=0 ; c<sizeof(buf) ; c++)
174 buf[c] = '\0';
175 while (i<SETUP_SECTS*512) {
176 c = SETUP_SECTS*512-i;
177 if (c > sizeof(buf))
178 c = sizeof(buf);
179 if (write(1,buf,c) != c)
180 die("Write call failed");
181 i += c;
182 }
183
// ���濪ʼ����systemģ���ļ������ļ�ʹ��gas���룬��˾���GNU a.outĿ���ļ���ʽ��
// ������ֻ����ʽ���ļ�������ȡ����a.out��ʽͷ���ṹ��Ϣ��1KB���ȣ������ж�system
// ��һ����Ч��a.out��ʽ�ļ�֮�ͰѸ��ļ������������ݶ�д���������Image�ļ���
// �У����رո��ļ���Ȼ����ʾsystemģ��ij��ȡ���system��������ݳ��ȳ���SYS_SIZE��
// ����128KB�ֽڣ�������ʾ������Ϣ���˳�����������0����ʾ�����˳���
184 if ((id=open(argv[3],O_RDONLY,0))<0)
185 die("Unable to open 'system'");
186 if (read(id,buf,GCC_HEADER) != GCC_HEADER)
187 die("Unable to read header of 'system'");
188 if (((long *) buf)[5] != 0) // ִ����ڵ��ֶ�a_entryֵӦΪ0��
189 die("Non-GCC header of 'system'");
190 for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
191 if (write(1,buf,c)!=c)
192 die("Write call failed");
193 close(id);
194 fprintf(stderr,"System is %d bytes.\n",i);
195 if (i > SYS_SIZE*16)
196 die("System is too big");
197 return(0);
198 }
199