PIGWORLD

学无止境

1.6 程序和进程

1.6 程序和进程

程序

程序是存在于磁盘上目录中的可执行文件。6exec函数中的任意一个,都可以将一个程序读入内存中并由内核执行(感觉这句没有翻译好,原句是:A program is read into memory and is executed by the kernel as a result of one of the six exec functions.)。我们将在8.10节中介绍这些函数。

进程和进程ID

一个正在执行中的程序实例被称为进程(process),该词语(进程)几乎会出现在本书中的每一页。一些操作系统用任务(task)来称呼一个正在运行中的程序。

UNIX系统确保每一个进程都拥有一个唯一的数字标识符,称为进程ID。进程ID总是非负整数。

例子

1.6中的程序打印出它的进程ID

如果我们把程序编译成a.out并执行它,我们会看到

$ ./a.out

hello world from process ID 851

$ ./a.out

hello world from process ID 854

该程序运行时调用getpid函数来获得进程ID

1 #include "apue.h"
2 
3 int
4 main(void)
5 {
6     printf("hello world from process ID %d\n", getpid());
7     exit(0);
8 }

1.6 打印进程ID

进程控制

进程控制主要使用三个函数:forkexecwaitpid。(exec函数有6个变体,我们通常把它们统称为exec函数。)

例子

使用一个简单的程序(图1.7)来展示UNIX系统的进程控制特性,该程序从标准输入读取命令并且执行这些命令。这是一个类似shell程序的本质(翻译得不好,原句是:This is a bare-bones implementation of a shell-like program.)。在这个30行的程序中有许多特性值得思考。

l         使用标准I/O函数fgets,一次从标准输入中读取一行。当输入文件终止符(通常是Control-D)作为一行的第一个字符时,fgets返回null指针,同时终止循环,接着终止进程。在18章中,我们描述所有特殊的终端字符(文件终止符,退格字符,整行擦除字符等等),并且介绍怎样改变它们。

l         fgets返回的每一行都终止于一个换行符和跟在换行符后面的一个null字节,我们使用标准的C函数strlen来计算字符串的长度,接着把换行符替换为一个null字节。这样做是因为execlp函数需要一个以null结束的参数,而不是以换行符结束的参数。

l         调用fork函数来建立一个进程,这个进程是一个调用者的拷贝。我们把调用者称为父进程,把新建立的进程称为子进程。那么fork函数返回子进程的非负进程ID给父进程,同时返回0给子进程。因为fork创建了一个新进程,我们说fork被调用一次就返回两次,一次返回给父进程,一次返回给子进程。

l         在子进程中,调用execlp来执行从标准输入读取的命令。这就把子进程替换为一个新的程序文件。fork函数后跟exec函数的组合,就是一些操作系统所谓的产生一个新进程。(翻译得不好,原句是:This replaces the child process with the new program file. The combination of a fork, followed by an exec, is what some operating systems call spawning a new process.)在UNIX系统中,这两部分被分为了独立的函数。第八章中将会介绍更多这方面的内容。

l         因为子进程调用execlp来执行新的程序文件,父进程就会等待直到子进程结束。这些工作由waitpid函数完成。waitpid函数中的pid参数代表了子进程的进程ID,该参数用来标识出需要等待的进程。waitpid函数也可以得到子进程的终止状态。在这个简单程序中的的status变量就代表了子进程的终止状态,在程序中我们没有使用这个值,但是我们可以通过检查这个值来确定子进程的终止状态。

l         这个程序最根本的限制在于我们不能像我们所执行的命令传递参数。例如,不能列举特定的目录。我们只可以在工作目录执行ls命令。为了能够传递参数,我们需要分析输入行,按某种习惯(可能的情况是使用空格或者制表符)区别出参数,接着把每一个参数作为独立的参数传递给execlp函数。尽管如此,这个程序仍然对UNIX系统进程控制函数进行了有用说明。

运行这个程序,我们得到下面的输出。注意我们的程序有一个不同的提示符,使用百分号(%)来区别于shell的提示符。

$ ./a.out

% date

Sun Aug 1 03:04:47 EDT 2004

% who

sar    :0        Jul 26 22:54

sar    pts/0      Jul 26 22:54  (:0)

sar    pts/1      Jul 26 22:54  (:0)

sar    pts/2      Jul 26 22:54  (:0)

% pwd

/home/sar/bk/apue/2e

% ls

Makefile

a.out

shell1.c

% ^D                           输入文件终止符

$                               shell提示符

 

#include "apue.h"
#include 
<sys/wait.h>

int
main(
void)
{
    
char    buf[MAXLINE];   /* from apue.h */
    pid_t   pid;
    
int     status;

    printf(
"%% ");  /* print prompt (printf requires %% to print %) */
    
while (fgets(buf, MAXLINE, stdin) != NULL) {
        
if (buf[strlen(buf) - 1== '\n')
            buf[strlen(buf) 
- 1= 0/* replace newline with null */

        
if ((pid = fork()) < 0) {
            err_sys(
"fork error");
        } 
else if (pid == 0) {      /* child */
            execlp(buf, buf, (
char *)0);
            err_ret(
"couldn't execute: %s", buf);
            exit(
127);
        }

        
/* parent */
        
if ((pid = waitpid(pid, &status, 0)) < 0)
            err_sys(
"waitpid error");
        printf(
"%% ");
    }
    exit(
0);
}

1.7 从标准输入读取命令并执行它们

 

符号^D用代表一个控制字符。控制字符是一种特殊的的字符,可以通过同时按下控制键(在你的计算机上通常为Control键或Ctrl键)和另一个键来产生它。Control-D,或者说^D,是默认的文件终止符。在18章讨论终止I/O的时候会看到更多的控制字符。

线程和线程ID

通常,一个进程只有一个线程(原句是:Usually, a process has only one thread of control one set of machine instructions executing at a time.不知道怎么翻译,留给大虾翻译)。当有多于一个的线程来控制不同部分时,一些问题就变得很容易解决。另外,多线程在多处理器系统上能够获得平衡性(又一句翻译得不爽:Additionally, multiple threads of control can exploit the parallelism possible on multiprocessor systems.)。

一个进程中的所有线程共享同一个地址空间,文件描述符,栈和进程相关的属性。因为能够访问相同的内存,线程必须同步访问它们自己的共享数据,以避免冲突。

和进程一样,线程由线程ID标识。尽管如此,线程ID对于进程ID来说是本地的。也就是说,一个进程中的线程ID在另一个进程中是没有意义的。当我们在进程中操作线程的时候,使用线程ID来指出特定的线程。

控制线程的函数和控制进程的函数是一样的。在进程模型建立很久以后,线程才被加入到UNIX系统中,然而,线程模型和进程模型之间有一些复杂的交互,在12章将会看到这些。

posted on 2006-01-06 00:25 PIGWORLD 阅读(661) 评论(1)  编辑 收藏 引用 所属分类: 《UNIX环境高级编程(第二版)》翻译

Feedback

# re: 1.6 程序和进程 2006-06-23 15:21 abc

ok  回复  更多评论   



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理