1.Init程序读取/etc/inittab配置文件
Init是系统的第一个进程,因此PID为1,也是所有进程的父进程,init启动后会读取配置文件/etc/inittab中的设定,其实/etc/inittab文件最主要的作用就是设定Linux的运行等级,其设定形式是“:id:5:initdefault:”,这就表明Linux需要运行在等级5上。Linux的运行等级设定如下:
0:关机
1:单用户模式
2:无网络支持的多用户模式
3:有网络支持的多用户模式
4:保留,未使用
5:有网络支持有X-Window支持的多用户模式
6:重新引导系统,即重启
2.执行/etc/rc.d/rc.sysinit脚本文件
在设定了运行等级后,Linux系统执行的第一个用户层文件就是/etc/rc.d/rc.sysinit脚本程序,它做的工作非常多,包括设定PATH、设定网络配置(/etc/sysconfig/network)、启动swap分区、设定/proc等等。如果你有兴趣,可以到/etc/rc.d中查看一下rc.sysinit文件。
3.执行/etc/rc.d/rcN.d脚本
根据运行级别的不同,系统会运行/etc/rc.d目录下的rc0.d到rc6.d中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务。
对每一个运行级别来说,在/etc/rc.d子目录中都有一个对应的下级目录。这些运行级别的下级子目录的命名方法是rcX.d,其中的X就是代表运行级别的数字。比如说,运行级别3的全部命令脚本程序都保存在/etc/rc.d/rc3.d子目录中。在各个运行级别的子目录中,都建立有到/etc/rc.d/init.d子目录中命令脚本程序的符号链接,但是,这些符号链接并不使用命令脚本程序在/etc/rc.d/init.d子目录中原来的名字。如果命令脚本程序是用来启动一个服务的,其符号链接的名字就以字母S打头;如果命令脚本程序是用来关闭一个服务的,其符号链接的名字就以字母K打头。
许多情况下,这些命令脚本程序的执行顺序都很重要。如果没有先配置网络接口,就没有办法使用DNS服务解析主机名!为了安排它们的执行顺序,在字母S或者K的后面紧跟着一个两位数字,数值小的在数值大的前面执行。比如:/etc/rc.d/rc3.d/S50inet就会在/etc/rc.d/rc3.d/S55named之前执行(S50inet配置网络设置,55named启动DNS服务器)。存放在/etc/rc.d/init.d子目录中的、被符号链接上的命令脚本程序是真正的实干家,是它们完成了启动或者停止各种服务的操作过程。当/etc/rc.d/rc运行通过每个特定的运行级别子目录的时候,它会根据数字的顺序依次调用各个命令脚本程序执行。它先运行以字母K打头的命令脚本程序,然后再运行以字母S打头的命令脚本程序。对以字母K打头的命令脚本程序来说,会传递Stop参数;类似地对以字母S打头的命令脚本程序来说,会传递Start参数。
附: /etc/init.d和/etc/rc.d/init.d的关系
/etc/init.d是指向/etc/rc.d/init.d的符号链接;
[root@localhost etc]#
[root@localhost etc]# pwd
/etc
[root@localhost etc]# ll | grep init.d
lrwxrwxrwx. 1 root root 11 4月 15 2014 init.d -> rc.d/init.d
[root@localhost etc]#
也就是说这两个目录的内容是一样的。那下面所提到的/etc/init.d也可以用/etc/rc.d/init.d来代替。
4.执行/etc/rc.local脚本文件
最后,init会执行/etc/rc.local脚本文件,rc.local就是在一切初始化工作后,Linux留给用户进行个性化的地方。你可以把你想设置和启动的东西放到这里。 执行完该脚本文件后系统就进入登录画面,如下图所示。
2.关机与重新启动
2.1 关闭机器
关闭操作系统,只需将run level 调整为0即可。或者说,系统会执行/etc/rc.d/rc0.d中的所有script,该目录的所有文件也是以K或S开头的一系列文件(内容省略)。
我们知道/etc/rc.d/rcN.d(这里的N可能为0-6,表示run level)中K开头的服务会停止,S开头的服务会启动,因此在run level为0的情况下,只会启动S00killall与S01halt这两项服务。我们知道killall这服务会终止所有正在运行的服务与服务器,而halt则会关闭系统。
因此我们可以执行:init 0 或使用shutdown、poweroff这类的命令关闭操作系统:shutdown -h 或 poweroff
若将电源选项编入内核中(这是默认值),则关闭系统时会一起将机器的电源关闭(关闭电源这项功能取决于主机板的芯片组,在近几年的主机板都支持这项功能)。
2.2 重新启动
重新启动系统,只需将initial模式调整为6即可。换言之,系统会执行/etc/rc.d/rc0.d中的所有script,该目录的文件也是些以K或S开头的文件。
我们知道/etc/rc.d/rcN.d(这里的N可能为0-6,表示run level)中K开头的服务会停止,S开头的服务会启动,因此在run level为6的情况下,只会启动S00killall与S01reboot这两项服务。我们知道killall这服务会终止所有正在运行的服务与服务器,而reboot则会重新启动系统。
因此我们可以执行:init 6 或使用reboot这类的命令关闭操作系统:reboot
注意:在关闭系统或是重新启动系统之前,别忘了执行sync这命令。sync可将缓冲区的数据写回硬盘中,避免数据的遗失。
因此,如果想要在关机前执行自定义脚本的话,其步骤如下:
将需要自动启动或关闭的脚本放在/etc/rc.d/init.d目录下,然后用命令chkconfig --add filename将自动注册开机启动和关机关闭。实质就是在rc0.d-rc6.d目录下生成一些文件连接,这些连接连接到/etc/rc.d /init.d目录下指定文件的shell脚本。
下面以关机前执行PG_stop.sh脚本为例介绍操作步骤:
1.在/etc/init.d目录下构建自定义脚本并附可执行权限,如:PG_stop.sh
[root@localhost bin]# ll /etc/init.d/ | grep P
-rwxr-xr-x 1 root root 299 08-11 17:56 PG_stop.sh
2.将/etc/init.d/PG_stop.sh 软连接到/etc/rc6.d目录下:
ln -s /etc/init.d/PG_stop.sh /etc/rc6.d/K0000PG_stop.sh
[root@localhost rc6.d]# ll /etc/rc6.d/ | grep K0000PG_stop.sh
lrwxrwxrwx 1 root root 22 08-11 11:29 K0000PG_stop.sh -> /etc/init.d/PG_stop.sh
注意名字务必要小于S00killall,使其才系统关闭前调用自定义脚本。这样系统在关闭的时候,就会运行PG_stop.sh 并加上stop参数,等同于执行命令PG_stop.sh stop。
3.在/var/lock/subsys/目录下构造一个同名的内容为空的自定义脚本PG_stop.sh
[root@localhost rc6.d]# ll /var/lock/subsys/ | grep P
-rw-r--r-- 1 root root 0 08-11 14:57 PG_stop.sh
上面的第二步和第三步可以用命令chkconfig --add PG_stop.sh来完成。在第二步中我们只在/etc/rc6.d里面建立了软连接,如果用chkconfig的话会同时在rc0.d-rc6.d目录下生成连接文件。
3 程序与信号
3.1 程序与子程序
当我们执行一个程序时,系统会因这个程序而产生一个或多个进程(process),并会给每个进程一个唯一的编号(Process ID,简称PID)。系统启动时由init开始第一个进程,PID为1,之后陆续启动其它进程。所有的进程都由某个现有进程所产生,这个现有的进程称为父进程(Parent Process ID,简称PPID),而父程序所产生的程序称为子程序。
我们可以试着执行ps这命令,过程如下:
[root@localhost ~]# ps
PID TTY TIME CMD
2207 pts/1 00:00:00 bash
2238 pts/1 00:00:00 ps
命令ps是process的简写,功能是列出正在执行的程序,以上面为例,我们使用ssh或是telnet登录系统则会通过BASH,并执行ps时,则会出现bash这程序,它的PID为2207。
3.2 信号
所谓的signal,指的是信号,也是系统重要的动作之一。系统、应用程序、甚至账号,都可以通过命令或是system call的方式对进程(process)下达信号。而该进程对于信号,有下列三种处理方式:忽略、终止、以及自行定义。我们可以通过kill -l来看看系统有哪些signal:
[root@home root]# kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
要终止进程,我们必须对该程序下达SIGKILL的信号,也就是通过kill的命令来对进程下达这个信号。首先我们可以通过ps -ef的命令了解进程的PID为何,再通过kill -KILL <PID>的命令终止该进程。举例而言,若我们知道某进程的PID为1234,可以通过以下的命令来终止该进程:kill -KILL 1234
由上面的列表可以知道,SIGKILL的编号是9,因此使用以下的命令也可以达到完全相同的效果:kill -9 1234
4.进程间通信
Interprocess communication是指内部进程的沟通。在操作系统之下,有许多进程必须互相交换信息。譬如许多程序会共享系统信息、同一程序所产生不同的进程会共享数据等。那么,进程之间要如何沟通呢?最常见的就是通过文件来沟通。举例而言,A程序把信息写到 /tmp/a.txt,而B程序则从 /tmp/a.txt当中读取数据,这样就达到沟通的目的了。除了文件,常见的沟通方式还包括share memory、semaphore、message queues、pipe等。Share memory与semaphore都是通过内存来存取数据,达到内部进程数据交换的目的。
我们可以使用ipcs来观看interprocess communication的状态:
[root@home root]# ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x5b0695a0 0 root 644 1048576 1
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 65536 apache 600 1
0x00000000 98305 apache 600 1
0x5b0695a2 163843 root 666 14
------ Message Queues --------
key msqid owner perms used-bytes messages
如同process一般,我们可以查看或是删除interprocess的id,通过ipcrm,我们可以将ipcs所看到的interprocess删除。语法如下:
ipcrm [ -M key | -m id | -Q key | -q id | -S key | -s id ]