unix的一切都是文件,我们把其中一些文件看做进程的发起者。 当一个文件以休眠的状态躺在磁盘上时,被看成是一个简单的文件。但当它被执行时,就可以理解为进程。和一个生命体一样,进程也会出生,也会生成其他
unix的一切都是文件,我们把其中一些文件看做进程的发起者。
当一个文件以休眠的状态躺在磁盘上时,被看成是一个简单的文件。但当它被执行时,就可以理解为进程。和一个生命体一样,进程也会出生,也会生成其他进程,当然也会死亡。unix中之所以会“发生”事情,正式因为进程的原因。
由于unxi是多任务环境,因此在一个大型系统上可以运行数百甚至数千个进程。进程属于内核的领域,由内核负责进程的管理。
进程和程序:
进程就是一个正在运行的程序实例。当一个程序开始执行时,就说这个进程出生了,只要这个程序生存,进程也就保持生存状态。在完成执行后,就说进程死亡。进程也有名字,通常就是被执行程序的名字。
尽管进程是由程序发起的,但不能将进程看作程序的同义词。它们在很多方面都有不同。首先,当两个用户运行同一程序时,磁盘上只有一个程序,但内存中却又两个进程。第二,在执行一个包含三个命令管道的shell脚本(也是程序)时,将会拥有三个进程。最后,一个程序在运行时可能会自行划分为两个或多个进程。
shell的职责是为用户服务,而内核则负责处理进程。它管理内存并调度进程,使每个进程都公平的分享CPU和其他资源。它还提供了一种机制,利用这种机制,进程能够执行有限时间,然后将控制交给另一进程。内核必须保存当前进程的状态(例如它当前正在执行的指令),以便再次执行进程时,内核知道从哪里去恢复。所有这些都会在一秒中执行一次,是用户感觉不到切换的过程。
文件和进程:
文件和进程有几个共同点。进程总是由另一个进程创建的,因此,除了第一个进程之外,每一个进程都有一个父进程。进程也被组织为层次结构,第一个进程占据了顶端,类似于文件系统的根目录。就像一个目录中有多个文件名一样,unix的多任务本质是一个进程可以拥有多个子进程。
文件拥有属性,进程也是如此。大多数进程属性都存储在进程表中,它是一种由内核在内存中维护的独立结构。我们可以说进程表是进程的inode。进程将一直在这个表中保留一个项目,知道它“正确地”死亡为止。因为这个表的大小有限,所以一个系统上可以运行的最大进程数也有限。我们必须理解“正确地”死亡的实际含义。
大多数进程属性都是由子进程从其父进程继承而来的,但是有一些属性不是继承来的,而是在进程出生时由内核分配的:
- 进程-id(PID) 每个进程都由一个称为进程-ID(PID)的独有整数加以识别,我们需要PID来控制进程,例如杀死进程。第一个进程的PID为0.
- 父进程 PID(PPID) 父进程的PID也可以在进程表中获得。当多个进程拥有相同的PPID时,直接杀死父进程要比分别杀死所有子进程更有效。
子进程在终止时变为僵尸。在父进程获取子进程的退出状态之前,内核不会删除其进程表项。父进程的永久死亡会将子进程变为孤儿,init会接管所有孤儿的父关系。
shell和init
用户登录时,会有一个代表shell的进程开始在终端上运行。这个进程可能是esh,ksh,csh或bash 。shell维护着一组环境变量,我们前面已经见过其中一些,例如PATH和HOME,shell自己的路径名存储在SHELL中,但它的PID存储在一个特殊“变量”$$中。
登录之后,登录shell的PPID总是为1.
init进程,系统的第二个进程。init是一个非常重要的进程,它不仅是用户shell的父进程,还负责生成系统中运行的每一个服务——例如打印,邮件,web等。
显示父进程 ps -f
尽管可能没有人正在使用系统,但有一些系统进程会一直保持运行。它们是在系统启动时由init(PID 1)繁衍的,init是登录shell的父进程。
[root@min ~]# ps -e PID TTY TIME CMD 1 ? 00:00:02 init 所有shell的父进程 2 ? 00:00:00 kthreadd 3 ? 00:00:00 migration/0 4 ? 00:00:00 ksoftirqd/0 5 ? 00:00:00 stopper/0 6 ? 00:00:00 watchdog/0 7 ? 00:00:14 events/0 8 ? 00:00:00 events/0 9 ? 00:00:00 events_long/0 10 ? 00:00:00 events_power_ef 11 ? 00:00:00 cgroup 12 ? 00:00:00 khelper 13 ? 00:00:00 netns 14 ? 00:00:00 async/mgr 15 ? 00:00:00 pm 16 ? 00:00:00 sync_supers 17 ? 00:00:00 bdi-default 18 ? 00:00:00 kintegrityd/0 19 ? 00:00:00 kblockd/0 20 ? 00:00:00 kacpid 21 ? 00:00:00 kacpi_notify 22 ? 00:00:00 kacpi_hotplug 23 ? 00:00:00 ata_aux 24 ? 00:00:00 ata_sff/0 25 ? 00:00:00 ksuspend_usbd 26 ? 00:00:00 khubd 27 ? 00:00:00 kseriod 28 ? 00:00:00 md/0 29 ? 00:00:00 md_misc/0 30 ? 00:00:00 linkwatch 32 ? 00:00:00 khungtaskd 33 ? 00:00:00 kswapd0 34 ? 00:00:00 ksmd 35 ? 00:00:00 khugepaged 36 ? 00:00:00 aio/0 37 ? 00:00:00 crypto/0 44 ? 00:00:00 kthrotld/0 45 ? 00:00:00 pciehpd 47 ? 00:00:00 kpsmoused 48 ? 00:00:00 usbhid_resumer 49 ? 00:00:00 deferwq 80 ? 00:00:00 kdmremove 81 ? 00:00:00 kstriped 112 ? 00:00:00 ttm_swap 229 ? 00:00:00 mpt_poll_0 230 ? 00:00:00 mpt/0 231 ? 00:00:00 scsi_eh_0 236 ? 00:00:00 scsi_eh_1 237 ? 00:00:00 scsi_eh_2 372 ? 00:00:00 flush-8:0 428 ? 00:00:00 jbd2/sda3-8 429 ? 00:00:00 ext4-dio-unwrit 515 ? 00:00:00 udevd 730 ? 00:00:00 vmmemctl 841 ? 00:00:00 kdmflush 844 ? 00:00:00 kdmflush 889 ? 00:00:00 jbd2/sda1-8 890 ? 00:00:00 ext4-dio-unwrit 891 ? 00:00:00 jbd2/sdb1-8 892 ? 00:00:00 ext4-dio-unwrit 893 ? 00:00:00 jbd2/sdb2-8 894 ? 00:00:00 ext4-dio-unwrit 895 ? 00:00:00 jbd2/sdb3-8 896 ? 00:00:00 ext4-dio-unwrit 938 ? 00:00:00 kauditd 1159 ? 00:00:00 dhclient 1216 ? 00:00:00 auditd 1240 ? 00:00:00 portreserve 1250 ? 00:00:00 rsyslogd 1272 ? 00:00:00 rpcbind 1294 ? 00:00:00 rpc.statd 1328 ? 00:00:00 dbus-daemon 1367 ? 00:00:00 hald 1368 ? 00:00:00 hald-runner 1400 ? 00:00:00 hald-addon-inpu 1418 ? 00:00:00 hald-addon-acpi 1473 ? 00:00:00 sshd 1552 ? 00:00:00 master 1565 ? 00:00:00 qmgr 1566 ? 00:00:02 crond 1588 tty1 00:00:00 mingetty 1590 tty2 00:00:00 mingetty 1592 tty3 00:00:00 mingetty 1594 tty4 00:00:00 mingetty 1596 tty5 00:00:00 mingetty 1598 tty6 00:00:00 mingetty 1647 ? 00:00:00 udevd 1648 ? 00:00:00 udevd 1649 ? 00:00:00 bluetooth 1651 ? 00:00:00 hald-addon-rfki 2162 ? 00:00:00 sshd 2166 pts/0 00:00:00 bash 2297 ? 00:00:00 pickup 2333 pts/0 00:00:00 ps
尽管可能没有人正在使用系统,但有一些系统进程会一直运行。它们在系统启动时由init(PID 1)繁衍的,init是登录shell的父进程。没有控制终端的系统进程很容易由TTY列中的?识别出来。没有和终端相关联的进程既不能写终端,也不能读终端。也不能按下[Ctrl-c]中断该进程。这些进程也称为守护程序。许多此类守护程序实际上都处于睡眠状态,仅在接受输入时才会醒来。
进程创建:
一个进程只能由另一个进程来创建,创建机制涉及三个阶段:fork(衍生)、exec(执行)、wait(等待),大多是根据同名系统调用而命名的。
- fork fork过程是通过创建已有进程的副本来创建另一个进程。新进程具有不同的PID,创建该进程的进程成为它的父进程。另外,父进程与子进程具有相同的进程映像。如果子进程没有执行其他程序,则父进程和子进程继续执行在调用fork时的相同代码。
- exec fork过程创建了进程,但这还不足以运行一个新程序。要运行新程序,用fork生成的子进程需要用新程序的代码和数据来覆盖自己的映像。这一机制成为exec,并说子进程要对一个新程序执行exec。这里并没有创建新的进程;被exec的进程的PID和PPID保持不变。
- wait 在子进程执行新的程序时,父进程通常会等待子进程死亡。随后,它会拾取子进程的退出状态,然后再做其他事情。
&----不注销
&是用于在后台运行的进程shell操作符。在这种情况下,父进程不会等待子进程的死亡。只要在命令行的最后加一个&,该命令就会在后台运行:
shell会立即返回被调用命令的PID。
对于大多数shell,系统变量$!存储了最后一个后台的作业的PID,所以可以用kill $!来杀死最后一个后台 进程。
nohup----安全注销
当一条命令nohup(no hangup,无挂断)一起运行时,甚至在用户注销后,该进程也能继续运行。