HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引

15.6.3 格式化输出字符串

您可以使用 WRITE 命令把字符串写入记录中。要排列记录中的各列,可以使用 F$FAO 函数定义记录字段,并把进程名和用户名放入这些字段中。您用 F$FAO 函数时,使用控制字符串定义记录的各字段;然后指定放入这些字段的值。

格式化记录字段的另一种方法使用字符串覆盖。然而,要注意 F$FAO 函数比字符串覆盖的能力更强。使用 F$FAO 函数可以执行更广泛的输出操作。

在以下例子中展示的命令过程使用 WRITE 命令显示系统上各进程的进程名和 PID 号:


$ ! Initialize context symbol to get PID numbers
$ CONTEXT = ""
$ ! Write headings
$ WRITE SYS$OUTPUT "Process Name     PID"
$ !
$ GET_PID:
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ WRITE SYS$OUTPUT F$GETJPI(PID,"PRCNAM"),"     ", F$GETJPI(PID,"PID")
$ GOTO GET_PID

注意,来自 WRITE 命令的输出把五个空格插入进程名和用户名之间,但是各列未对齐:


Process Name     PID
MARCHESAND     2CA0049C
TRACTMEN     2CA0043A
FALLON     2CA0043C
ODONNELL     2CA00453
PERRIN     2CA004DE
CHAMPIONS     2CA004E3

在这个例子中的命令过程使用 F$FAO 函数定义一个 16 字符的字段和一个 12 字符的字段。F$FAO 函数把进程名放入第一个字段,跳过一个空格,然后把 PID 号放入第二个字段:


$ ! Initialize context symbol to get PID numbers
$ CONTEXT = ""
$ ! Write headings
$ WRITE SYS$OUTPUT "Process Name     PID"
$ !
$ GET_PID:
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ LINE = F$FAO("!16AS !12AS", F$GETJPI(PID,"PRCNAM"), F$GETJPI(PID,"PID"))
$ WRITE SYS$OUTPUT LINE
$ GOTO GET_PID

现在,执行这个过程时,这些列将对齐:


Process Name     PID
MARCHESAND       2CA0049C
TRACTMEN         2CA0043A
FALLON           2CA0043C
ODONNELL         2CA00453
PERRIN           2CA004DE
CHAMPIONS        2CA004E3

以下例子使用覆盖把进程名放入符号 RECORD 的前 16 个字符 (在偏移 0 开始) 中。然后把 PID 号放入后 12 个字符 (在偏移 17 开始) 中。


$ ! Initialize context symbol to get PID numbers
$ CONTEXT = ""
$ ! Write headings
$ WRITE SYS$OUTPUT "Process Name     PID"
$ !
$ GET_PID:
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ RECORD[0,16]:= 'F$GETJPI(PID,"PRCNAM")'
$ RECORD[17,12]:= 'F$GETJPI(PID,"PID")'
$ WRITE SYS$OUTPUT RECORD
$ GOTO GET_PID

这个过程产生与用 F$FAO 函数建立的同样类型格式的列:


Process Name     PID
MARCHESAND       2CA0049C
TRACTMEN         2CA0043A
FALLON           2CA0043C
ODONNELL         2CA00453
PERRIN           2CA004DE
CHAMPIONS        2CA004E3

15.7 处理数据类型

您可以使用以下词法函数把数据从字符串转换为整数,或者从整数转换为字符串:

F$CVSI 从字符串抽取位字段,并把结果作为有符号值转换为一个整数
F$CVUI 从字符串抽取位字段,并把结果作为无符号值转换为一个整数
F$INTEGER 把字符串表达式转换为整数
F$STRING 把整型表达式转换为字符串
F$TYPE 确定符号的数据类型

15.7.1 转换数据类型

使用 F$INTEGER 和 F$STRING 函数在整数和字符串之间进行转换。例如,以下命令过程转换数据类型。如果输入一个字符串,该命令过程展示等价的整数。如果输入一个整数,则命令过程展示其等价串。注意 F$TYPE 函数是如何用来形成一个 GOTO 语句中的标号名;F$TYPE 返回 "STRING" 或 "INTEGER",视这个符号的数据类型而定。


$ IF P1 .EQS. "" THEN INQUIRE P1 "Value to be converted"
$ GOTO CONVERT_'F$TYPE(P1)'
$
$ CONVERT_STRING:
$ WRITE SYS$OUTPUT "The string ''P1' is converted to ''F$INTEGER(P1)'"
$ EXIT
$
$ CONVERT_INTEGER:
$ WRITE SYS$OUTPUT "The integer ''P1' is converted to ''F$STRING(P1)'"
$ EXIT

15.7.2 求表达式的值

有些命令,例如 INQUIRE 和 READ,只接受字符串数据。如果使用这些命令获得想要作为整型表达式求值的数据,那么使用 F$INTEGER 函数转换并求这个数据的值。

注意,当要把符号 EXP 使用为 F$INTEGER 函数的一个变元时,必须用省略号 (' ') 括住它。这使得 DCL 在符号替换的第一个阶段替换 EXP 值。

在以下例子中,F$INTEGER 函数用来求一个整型表达式的值:


$ INQUIRE EXP "Enter integer expression"
$ RES = F$INTEGER('EXP')
$ WRITE SYS$OUTPUT "Result is",RES

这个命令过程的输出将是如下所示:


Enter integer expression: 9 + 7
Result is 16

值 "9 + 7" 被替换。当 F$INTEGER 函数处理变元 "9 + 7" 时,它求这个表达式的值并返回正确的结果。

15.7.3 确定符号是否存在

使用 F$TYPE 函数来确定一个符号是否存在。如果符号未定义,那么 F$TYPE 函数返回空串。例如:


   .
   .
   .
$ IF F$TYPE(TEMP) .EQS. "" THEN TEMP = "YES"
$ IF TEMP .EQS. "YES" THEN GOTO TEMP_SEC
   .
   .
   .

这个过程测试符号 TEMP 是否已在以前定义。如果它已定义,就保留 TEMP 的当前值。如果 TEMP 没有定义,IF 语句则把值 "YES" 赋予 TEMP。


第 16 章
理解进程和批量作业

进程是 OpenVMS 操作系统建立的环境,使您与系统进行交互。进程可以是一个分离进程 (独立于其他进程的进程) 或一个子进程 (其存在和资源依赖于另一个进程的进程)。主进程,也称为父进程,是一个分离进程。本章描述:

  • 解释进程环境
  • 使用子进程
  • 连接虚拟终端上的断开进程
  • 处理批量作业

如何建立进程

执行以下任务之一时,系统就建立一个进程:

  • 注册
    系统为每个交互用户建立一个进程。
  • 提交批量作业
    系统为每个批量作业建立一个进程。当批量作业完成时,系统就删除这个进程。
  • 派生子进程
    使用 SPAWN 命令时,系统就建立一个进程。
  • 运行程序
    使用 /DETACHED 限定词或 /UIC=uic 限定词运行程序时,系统就建立一个进程。

16.1 解释进程环境

进程使用的特征,例如特权、符号和逻辑,形成一个进程环境。系统从用户授权文件 (UAF) 获得进程唯一的特征。UAF 列出那些准许存取系统的用户,并定义每个用户进程的特征。系统管理员通常维护 UAF。在进程中,系统每次只能执行一个程序 (也称为映象或可执行映象)。

要显示当前进程的进程环境,输入 SHOW PROCESS/ALL 命令。

以下例子展示一个进程环境:


11-DEC-2002 13:30:37.12 (1)  用户: CLEAVER (2)  进程 ID: 24E003DC  (3)
                            节点: ZEUS         进程名: "CLEAVER"  (4)
终端:           VTA2195:  TNA2170:  (主机: 16.32.123.45 端口: 6789)                                                 (5)
用户标识:       [DOC,CLEAVER]    (6)
基本优先级:      4               (7)
默认文件说明:    DISK1:[CLEAVER] (8)
Kthreads 数:    1

分配设备:        ALPHAI$VTA2195:

进程定额:                        (9)
 帐户名: DOC
 CPU 极限:                 无限  直接 I/O 极限:         1024
 缓冲 I/O 字节定额:       119616  缓冲 I/O 极限:        1024
 定时器队列条目定额:         400  打开文件定额:           299
 分页文件定额:            100080  子进程定额:             30
 默认页故障簇:                64  AST 定额:              798
 入队定额:                  5000  共享文件极限:            0
 分离进程最大数量:             0   活动作业最大数量:        0

 会计资料:                       (10)
 缓冲 I/O 计数:       16424  峰值工作区大小:      13920
 直接 I/O 计数:       12014  峰值虚拟大小:       185392
 页故障数:            11113  装上卷数:                0
 映象启动数:             68
 花费的 CPU 时间:    0 00:04:18.55
 连接时间:           0 00:08:22.76

授予特权:
 NETMBX       TMPMBX

进程特权:                       (11)
 GROUP                可能影响同组的其他进程
 TMPMBX               可能建立临时邮箱
 OPER                 操作员特权
 NETMBX               可能建立网络设备

进程权:                         (12)
 CLEAVER                           资源
 INTERACTIVE
 LOCAL

系统权:
 SYS$NODE_ZEUS

自动不搁置架上: 开

映象转储: 关

Soft CPU 亲合: 关

分析式样: 传统的

起点 RAD: 0

调度种类名: 没有

进程动态内存区域                  (13)
  当前大小 (Kb)         128.00   当前总大小 (页)              256
  未用空间  (Kb)        111.18   在用空间 (Kb)              16.81
  最大块大小 (Kb)       109.69   最小可变块 (字节)              8
  未用块数                  10   未用块少于或等于64 字节        4

在这个作业中有 1 个进程: (14)

  CLEAVER (*)

检查这个例子时,注意以下几点:

  1. 当前日期和时间
    SHOW PROCESS/ALL 命令执行时的日期和时间。
  2. 用户名
    赋予与进程关联帐户的用户名。
  3. 进程标识 (PID) 号
    系统为进程分配的唯一编号。SHOW PROCESS 命令以十六进制数形式显示 PID 号。
  4. 进程名
    赋予进程的名称。因为进程名是唯一的 (在特定的 UIC 组内),因此用一个帐户注册的第一个进程被赋予其用户名。用同样帐户注册的后续进程赋予终端名。您可以使用 DCL 命令 SET PROCESS/NAME 更改进程名 。
  5. 用户标识码 (UIC)
    赋予与进程关联的帐户的组和成员号 (或字母) (例如,[DOC,CLEAVER])。UIC 的一部分标识您所属的工作组。允许组中用户比组间用户更自由地共享文件或系统资源 。
  6. 优先级
    进程的当前优先级。
  7. 默认文件说明
    当前设备和目录。使用 DCL 命令 SET DEFAULT 更改当前默认。
  8. 进程定额
    与进程关联的定额 (限制)。使用带 /QUOTAS 或 /ALL 限定词的 SHOW PROCESS 命令检查这些定额。
  9. 会计资料
    连续更新计算进程的内存使用和 CPU 时间。使用带 /ACCOUNTING 或 /ALL 限定词的 SHOW PROCESS 命令检查这个资料。
  10. 进程特权
    准予进程的特权。特权对某些用户限制某些系统活动的性能。使用带 /PRIVILEGES 或 /ALL 限定词的 SHOW PROCESS 命令检查您的特权。
  11. 进程权
    与存取控制列表 (ACL) 保护一起使用的系统定义标识符。标识符提供在 ACL 中指定用户的方法。ACL 是一个定义准予或拒绝用户存取对象 (如文件、设备或邮箱) 的安全工具。
  12. 进程动态内存区域
    进程当前对动态内存的使用。执行映象时,系统把动态内存分配给映象。当进程不再需要这个内存时,系统就把它分配给另一个进程。使用 /MEMORY 或 /ALL 限定词的 SHOW PROCESS 命令检查这个信息 。
  13. 树中进程
    一列属于父进程的子进程。一个星号 (*) 出现在当前进程之后。使用 SHOW PROCESS/SUBPROCESSES 或 /ALL 命令检查这个列表 。

16.2 使用分离进程

分离进程或是交互的,或是非交互的,视父进程而定。您或者操作系统执行注册,这取决于提供给 DCL 命令 RUN 或建立进程系统服务 ($CREPRC) 的变元。(RUN 和 $CREPRC 两者都执行 SYS$SYSTEM 的 LOGINOUT.EXE 映象。)

16.3 使用子进程

SPAWN 命令允许您建立当前进程的子进程。在这个子进程中,您可以与系统进行交互,并且从这个子进程注销而返回到父进程,或者在父进程和子进程之间转换。任何时候只有一个进程在执行。

系统的每个用户用一个作业树表示作业树是所有进程和子进程的分层结构,而主进程处于顶端。子进程依赖于父进程,并且当父进程退出时被删除。按照默认,子进程名采用后面跟随下划线和唯一编号的父进程名。例如,如果父进程的名称是 DOUGLASS,那么子进程命名为 DOUGLASS_1、DOUGLASS_2,以此类推。

16.3.1 使用子进程派生任务

要中断一个任务,就执行第二个任务,然后返回到原始任务,可以使用 Ctrl/Y 中断第一个任务,派生执行第二个任务的子进程,退出子进程,然后输入 CONTINUE 命令返回到第一个任务。按照默认,当您建立一个子进程时,父进程睡眠并且控制转换到子进程的 DCL 级。您的默认目录是父进程的当前目录。例如,如果按下 Ctrl/Y 中断 EVE 编辑对话期,那么输入 CONTINUE 命令并且按下 Ctrl/W 来刷新屏幕。

16.3.2 使用子进程执行多项任务

在继续处理原始任务的同时要执行第二个任务,您可以使用 SPAWN/NOWAIT 命令建立子进程。SPAWN/NOWAIT 生成一个非交互的、类似批量作业的子进程,并且只用于执行不需要输入的命令。

因为父和子进程两者是并行执行,因此两个都尝试控制终端。要避免冲突,也要指定以下几点:

  • /OUTPUT 限定词
    指出子进程应该把输出写入指定文件,而不是终端
  • SPAWN 命令参数或 /INPUT 限定词
    指出子进程应该执行指定的命令,而不是从终端读取输入

指定 SPAWN 命令的 /INPUT 限定词时,子进程建立为一个非交互进程,并且当遇到严重出错或文件结束指示符时就退出。在 DCL 级,Ctrl/Z 被视为文件结束指示符。

16.3.3 建立子进程

由于建立的每个进程是唯一的,因此在一个进程中执行的命令通常不影响其他任何进程。然而,因为终端控制在进程之间传递,故影响终端特征的命令 (例如,SET TERMINAL) 会影响控制终端的任何进程。例如,如果一个进程禁止屏幕显示并且退出时没有恢复它,那么对下一个获得终端控制的进程保持禁止屏幕显示。使用 SET TERMINAL 命令重新设置任何改变的终端特征。

在以下例子中,用户按下 Ctrl/Y 中断命令映象 (TYPE 命令),派生一个子进程,从子进程退出,然后返回到原始进程:


$ TYPE MICE.TXT
Once the weather turns cold, mice may find a crack in the
foundation and enter your house.  They are looking for food and
shelter from the harsh weather ahead.
   .
   .
   .
[Ctrl/Y]
$ SPAWN
%DCL-S-SPAWNED, process DOUGLASS_1 spawned
%DCL-S-ATTACHED, terminal now attached to process DOUGLASS_1
$ MAIL
MAIL>
   .
   .
   .
MAIL> EXIT
$ LOGOUT
  Process DOUGLASS_1 logged out at 31-DEC-1999 12:42:12.46
%DCL-S-RETURNED, control returned to process DOUGLASS
$ CONTINUE
Once inside, they may gnaw through electrical wires and raid
your food. Because mice reproduce so quickly, what started
as one or two mice can quickly become an invasion.  If you seal
the cracks and holes on the exterior of your foundation, you can
prevent these rodents from ever getting in.

16.3.4 退出子进程

要退出 SPAWN 命令建立的子进程,使用以下命令之一:

  • LOGOUT
    使用 LOGOUT 命令退出子进程时,这个子进程被删除 (以及它建立的任何子进程),并且返回父进程。
  • ATTACH
    使用 ATTACH 命令退出子进程时,子进程睡眠,并且终端控制被传递到指定进程。必须指定一个进程名作为 ATTACH 命令的一个参数,或者指定一个进程标识 (PID) 号作为 ATTACH 命令的 /IDENTIFIER 限定词的值。

以下例子展示如何退出子进程 DOUGLASS_1,并且连接到进程 DOUGLASS:


$ ATTACH DOUGLASS
%DCL-S-RETURNED,控制返回到进程 DOUGLASS
$ SHOW PROCESS
11-DEC-2002 10:34:58.50   用户: DOUGLASS         进程 ID:  2061C478
                          节点: ALPHAI           进程名:  "DOUGLASS"
终端:           VTA2195:  TNA2170:  (主机: 16.32.123.45 端口: 6789)

用户标识 :    [DOC,DOUGLASS]
基本优先级 :      4
默认文件说明:    DISK1:[DOUGLASS]
Kthreads 的数目: 1

分配的设备:  ALPHAI$VTA2195:

Soft CPU 亲合: 关

16.3.5 子进程环境

子进程环境是子进程从父进程继承的环境。按照默认,子进程继承以下项目: 默认、特权、符号、逻辑名、控制字符、消息格式、校验状态和键定义。这些项目共同为子进程建立一个环境。

以下项目不从父进程继承:

  • 进程标识 (PID) 号
    系统为每个建立子进程分配一个唯一 PID 号。
  • 进程名
    按照默认,子进程名包括父进程名,后面跟随一个下划线和一个整数。使用 SPAWN 命令的 /PROCESS 限定词指定与默认不同的进程名。进程名必须唯一。
  • 建立的命令
    父进程使用 SET COMMAND 命令定义的命令不复制到子进程。要在子进程中使用已建立的命令,必须使用 SET COMMAND 建立用于子进程的命令。
  • 授予特权
    当派生子进程时,其进程环境包含父进程的特权,而不是您授权允许的特权。例如,如果您计划派生一个子进程的同时,在 Mail 中并且执行一个特权操作,那么您必须在父进程中在调用 Mail 之前首先设置适当的特权。

您可以使用以下 SPAWN 命令限定词阻止子进程继承许多项目:

SPAWN 命令限定词 抑制或更改的项目
/CARRIAGE_CONTROL, /PROMPT DCL 提示
/NOCLI CLI (命令语言解释程序;按照默认是 DCL )
/NOKEYPAD 小键盘定义
/NOLOGICAL_NAMES 逻辑名
/NOSYMBOL 符号

/SYMBOL 和 /LOGICAL_NAMES 限定词不影响系统定义的符号 (例如 $SEVERITY 和 $STATUS) 或者系统定义的逻辑名 (例如 SYS$COMMAND 和 SYS$OUTPUT)。

因为把逻辑名和符号复制到子进程可能是耗时的 (几秒),所以您可能想要把 /NOLOGICAL_NAMES 和 /NOSYMBOL 限定词用于 SPAWN 命令,除非您计划在子进程中使用这些逻辑名或符号。如果频繁地使用子进程,那么 ATTACH 命令可提供更有效的方法进入和退出子进程。这个方法允许您把控制快速地在父进程和子进程之间传递,而不是重复等待系统建立新的子进程。


前页 后页 目录 索引