1.进程
1)每个进程还有一个所有者。一般来说,您启动的任务(如您的 shell 和命令)的所有者就是您。系统服务的所有者可能是特殊用户或超级用户 root。例如,为了增强安全性,Apache HTTP Server 的所有者一般是一个名为 www 的专用用户,该用户能提供 Web 服务器所需的的文件访问权限,但不包含其他权限。
2)进程的所有权可能会改变,但必须严格保持其独占性。一个进程在任何时候都只能有一个所有者。
3)最后,每个进程都具有权限。一般来说,进程的权限与其所有者的权限是相称的。(例如,如果您无法在命令行 Shell 中访问某个特定文件,则您从 Shell 中启动的程序也会继承同样的限制。)这一继承规则有一个例外情况,即应用程序启用了特殊的 setuid 或 setgid 位,如 ls 显示的那样,在此情况下,某个进程可能会获得比其所有者更高的权限。
2.setUID
If the process has appropriate privileges, setuid() shall set the real user ID, effective user ID, and the saved set-user-ID of the calling process to uid.
让执行该程序的用户拥有文件属主的权限
setuid 位可以使用 chmod u+s
进行设置。setuid 的权限如下所示:
$ ls -l /usr/bin/top -rwsr-xr-x 1 root wheel 83088 Mar 20 2005 top |
setgid 位可以使用 chmod g+s
设置:
$ ls -l /usr/bin/top -r-xr-sr-x 1 root tty 19388 Mar 20 2005 /usr/bin/wall |
一个 setuid 进程(如启动 top)是用拥有该文件的用户权限运行的。因此,当您运行 top 时,您的权限会被提升,与 root 的权限等同。类似地,一个 setgid 进程是用与文件的组所有者相关联的权限运行的。
Eg:
-rwxrwx--- 1 gl enia 24 May 12 10:42 test.sh
[gl@int8 xiuyun]$ chmod u+s test.sh
[gl@int8 xiuyun]$ ls -ltr test.sh
-rwsrwx--- 1 gl enia 24 May 12 10:42 test.sh
[gl@int8 xiuyun]$ chmod g+s test.sh
[gl@int8 xiuyun]$ ls -ltr test.sh
-rwsrws--- 1 gl enia 24 May 12 10:42 test.sh
3.UNIX 内核在系统启动序列中产生了第一个进程。
第一个进程被恰如其分地称为 init,所有其他系统进程的亲缘关系最终都可以追溯到 init。实际上,init 的进程编号是 1。如果您要查看 init 的状态,可键入
ps -l 1
:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 68 0 - 373 select ? 0:02 init [2] |
正如您所看到的,init 的所有者 (UID
) 是 0
(root)。和系统中所有其他进程不同的是,init 没有父进程,它的父进程 ID (PPID) 为 0
。
4. 这里是另一个可供尝试的实验。键入:
sleep 10 & sleep 10 & sleep 10 & ps -o pid,ppid,uname,command,state,stime,tim |
您应该会看到类似这样的内容:
$ sleep 10 & sleep 10 & sleep 10 & ps -o pid,ppid,uname,command,state,stime,time PID PPID USER COMMAND S STIME TIME 16351 16350 mstreic -bash S 11:23 00:00:00 16843 16351 mstreic sleep 10 S 11:42 00:00:00 16844 16351 mstreic sleep 10 S 11:42 00:00:00 16845 16351 mstreic sleep 10 S 11:42 00:00:00 16846 16351 mstreic ps -o pid,ppid,u R
11:42
00:00:00
|
命令行生成四个新进程。在每个 sleep
命令后键入 &
,在后台运行每一个命令,或与 Shell 并行。 ps
是生成的另一个进程,但它是在前台运行的,可以防止 shell 在该进程终止之前运行其他命令。而且,如 PPID 的值所示,所有四个进程都是 Shell 的后代。三个 sleep
命令都被标为 S
,因为没有哪个进程会在它们睡眠时使用资源。
5.kill %N ,其中 N 是该命令的标签。
如要将某个命令由后台移到前台,请键入 fg %N
$ sleep 10 & sleep 10 & sleep 10 & [1] 16843 [2] 16844 [3] 16845 $ jobs [1] Running sleep 10 & [2] Running sleep 10 & [3] Running sleep 10 & |
此处,为了方便起见,三个工作分别用标签标为 1,2 和 3。数字 16843、16844 和 16845 分别是每个进程的进程 ID。因此,后台任务 1 即为进程 ID 16843。
您可以利用这些标签,从命令行操作您的后台工作。例如,如要终止某个命令,键入 kill %N
,其中 N
是该命令的标签。如要将某个命令由后台移到前台,请键入 fg %N
:
$ sleep 10 & sleep 10 & sleep 10 &
[7] 17741 [8] 17742 [9] 17743 $ kill %7
$ jobs
[7] Terminated sleep 10 [8]- Running sleep 10 & [9]+ Running sleep 10 &
$ fg %8
sleep 10 |
Tip(有时俺也这么用)
Kill -9 PID PID PID…
6.进程池
某些进程会一直存活(如 init),而某些进程会以新的形式重生(如您的 shell)。最终大多进程都会因自然原因(即程序运行结束)而消亡。
此外,您还可以将某个进程放在一个挂起的动作序列中,等待被再次激活。正如先前的示例所示,您可以用 kill
提前终止某个进程。
当某个命令在前台运行时,如果您希望将它挂起,请按 Ctrl + Z:
$ sleep 10 (Press Control-Z)
[1]+ Stopped sleep 10 $ ps PID PPID USER COMMAND S STIME TIME 18195 16351 mstreic sleep 10 T 12:44 00:00:00 |
Shell 已将命令挂起,为了方便起见,还为它分配了一个标签。您可以像先前那样使用这个标签,以终止工作或让工作返回前台。您还可以使用 bg
命令在后台恢复这个进程:
bg %1 [1]+ sleep 10 & |
当某个命令在前台运行时,如果您想终止它,请按 Ctrl + C:
$ sleep 10 (Press Control-C $ jobs $ |
在内部,Shell 使用 UNIX 信号来影响进程的状态。信号是一个事件,它被用来向某个进程发出警报。操作系统生成许多信号,但您可以将信号从一个进程发送到另一个进程,甚至能让某个进程给自己发送信号。
UNIX 包括多种信号,它们大多都有特殊目的。例如,如果您将信号 SIGSTOP
发送到某个进程,该进程将挂起。(要获取信号的完整列表,请键入 man 7 signal
或键入 kill -L
)。您可以用 kill
命令发送信号。
$ sleep 20 & [1] 19988 $ kill -SIGSTOP 19988
$ jobs [1]+ Stopped sleep 20 |
起初,sleep
命令在后台启动,其进程 ID 为 19988。在发送 SIGSTOP
之后,该进程会改变状态,变为挂起或停止。发送另一个信号 SIGCONT
,重新激活进程,该进程将从上次停止的地方继续执行。
也就是说,每次您按 Ctrl + Z 时,您的 shell 将向前台发送 SIGSTOP
信号。bg
命令发送 SIGCONT
。而 Ctrl + C 则会发送 SIGTERM
,要求立即终止进程。
一些信号可以被某个进程阻塞,应用程序可以通过设计,显式地“捕捉 (catch)”信号,并以一种特殊的方式对每个事件作出反应。例如,系统服务 xinetd 会按需要启动其他网络服务,它在收到 SIGHUP
时会重新读取它的配置文件。在 Linux 中,向 init 发送信号,可能会改变系统的运行级别,甚至会导致系统关闭。
进程甚至可以给自己发送信号。想像一下,您正在编写一个游戏,想留给用户五秒钟时间作出反应。您的代码可以设置一个五秒钟的定时器,接下来继续进行重绘屏幕等操作。当定时器的时间耗尽后,将有一个 SIGALRM
信号被送回您的进程。呯!时间到!
超级用户 root 可以向任何进程发送信号。
7.kill %1
和 kill 1
有什么区别?
kill %1
会终止标签为 1 的后台工作。kill 1
会终止 init,当必须关闭计算机时,将向操作系统发送这个信号。)