Unix环境高级编程—进程控制(三)
一、解释器文件
解释器文件属于文本文件,起始行形式为:
#! pathname[optional-argument]
我们创建一个只有一行的文件如下:
#!/home/webber/test/echoall.c foo
然后通过进程fork一个子进程execl寻找到这个文件路径下,我们将看到的是/home/webber/test/echoall.c 作为第一个参数被传了进来,foo成为第二个参数,
然后才是execl函数内指定的其他argv的值。即exec族函数的处理是把#!后面的字符串做为命令,后面加上execl参数列表中指定。
在书中例子中,
#!/usr/bin/awk -f
-f 的选项是必须的,它告诉awk在什么地方找到awk程序。
二、函数system
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed.
During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system函数用于执行一个shell命令,它对fork、exec、waitpid的进行封装,变为一个对外的函数接口,进行了所需的各种出错处理和各种信号处理。
#include<stdlib.h>
int system(const char *cmdstring)
返回值:因为system在实现中调用了fork、exec、waitpid,所以有三种返回值。如下:
1) fork失败或waitpid返回除EINTR之外的出错,则system返回-1,并且设置errno来指示错误类型。
2) exec失败(表示不能执行shell),则返回值相当于shell执行exit(127),即返回定义的错误码(command not found)。
3) 三个调用的函数都执行成功,则system的返回值是shell的终止状态。(WIFEXITED,WIFSIGNALED,WIFSTOPPED,WIFCONTINUED)
The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command other- wise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127).
If the value of command is NULL, system() returns non-zero if the shell is available, and zero if not. system() does not affect the wait
status of any other children.
注意:使用system函数调用在某些情况下需要谨慎。比如,一个进程以root权限运行,当它想生产一个子进程执行以普通用户权限就能执行的任务时,绝不能用system函数去开启子进程,因为system在fork一个子进程时把root的ID也复制给了子进程,然后立即exec去执行,这样当真正的子进程以普通用户权限去执行任务时,我们geteuid()会返回0,即子进程的有效用户ID具有root权限,这是很危险的安全漏洞。对于这种情况,我们应该在fork之后,exec之前改回普通用户权限,而不能调用封装好的system函数。
三、进程会计
accton(8)命令开启或关闭进程会计,每当进程结束时,内核就写一个会计记录,记录命令名、所使用的CPU时间总量、用户ID和组ID、启动时间等。在Linux中,
该记录写在/var/account/pacct文件中。会计记录所需的数据都由内核保存在进程表中,并在一个新进程fork被创建时初始化。进程终止时写一个会计记录。
这产生两个后果:
1).我们不能获取永远不终止的进程的会计记录。例如init、守护进程daemon
2).在会计文件中记录的顺序对应于进程终止的顺序,而非启动顺序。
注意:会计记录对应与进程而不是程序。在这里,我认为进程是大于程序的,可以表述为:
首先,父进程fork了一个子进程,然后子进程exec一个程序A(通过pathname等找到程序A),同时,该子进程还可以再exec一个程序B。因此说进程大于程序,
程序是用某一进程exec出来的。
再回到会计记录,在上述表述中,进程会计只会记录exec出来的程序B,但CPU时间是A、B之和。
一个人在口令文件中可以有多个登录项,它们的用户ID相同,但登陆shell不同。登录名由getlogin()函数获取。
四、进程调度
nice函数 属于系统调用,它的作用是通过调整nice值选择以更低的优先级运行,nice值越小,cpu占用率越高,进程越“友好”,优先级也就越高。
在Linux2.26.32内核版本中,nice值的范围为-20~19. ( Nicenesses range from -20 (most favorable scheduling) to 19 (least favorable).)
经过测试,在单核CPU的Linux系统中,如果两个进程并行运行,在相同nice值的情况下,我们top观察两个进程,会发现cpu占用大约各为50%,
但是如果其中一个进程调高了nice值,则系统会认为它不“友好”,从而给它分配更低的cpu占用率,它执行任务的效率会明显变低。
五、进程时间
times命令是内建命令。作用:
Print the accumulated user and system times for the shell and for processes run from the shell. The return status is 0.
time命令,作用:测量一个命令的运行的三种时间,分别为:实际使用时间(real time)、用户态使用时间(the process spent in user mode)、
内核态使用时间(the process spent in kernel mode)
times函数,返回墙上时钟时间,调用方式如下:
clock_t times(struct tms *buf);
buf指向的tms结构,该结构定义如下:
Struct tms {
clock_t tms_utime; /*user CPU time */
clock_t tms_stime; /*system CPU time */
clock_t tms_cutime; /*user CPU time ,terminated children*/
clock_t tms_cstime; /*system CPU time ,terminated children*/
}
下面是书中用times函数以及结合了整章知识点,写了一个具有time命令功能的程序。
其中,输入的argv[]需要有双引号。
#include "apue.h"
#include <sys/times.h> static void pr_times(clock_t, struct tms *, struct tms *);
static void do_cmd(char *); int
main(int argc, char *argv[])
{
int i; setbuf(stdout, NULL);
for (i = 1; i < argc; i++)
do_cmd(argv[i]); /* once for each command-line arg */
exit(0);
} static void
do_cmd(char *cmd) /* execute and time the "cmd" */
{
struct tms tmsstart, tmsend;
clock_t start, end;
int status; printf("\ncommand: %s\n", cmd); if ((start = times(&tmsstart)) == -1) /* starting values */
err_sys("times error"); if ((status = system(cmd)) < 0) /* execute command */
err_sys("system() error"); if ((end = times(&tmsend)) == -1) /* ending values */
err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
} static void
pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend)
{
static long clktck = 0; if (clktck == 0) /* fetch clock ticks per second first time */
if ((clktck = sysconf(_SC_CLK_TCK)) < 0)
err_sys("sysconf error"); printf(" real: %7.2f\n", real / (double) clktck);
printf(" user: %7.2f\n",
(tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck);
printf(" sys: %7.2f\n",
(tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck);
printf(" child user: %7.2f\n",
(tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
printf(" child sys: %7.2f\n",
(tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);
}
Unix环境高级编程—进程控制(三)的更多相关文章
- UNIX环境高级编程——进程控制
一.进程标识符 ID为0的进程是调度进程,常常被称为交换进程.该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被称为系统进程.进程ID 1通常是init进程,在自举过程结束时由内核调用.ini ...
- Unix环境高级编程—进程控制(二)
一.函数wait和waitpid 今天我们继续通过昨天那个死爹死儿子的故事来讲(便于记忆),现在看看wait和waitpid函数. #include<sys/wait.h> pid_t w ...
- unix环境高级编程----进程控制wait()
一.wait()函数 当一个进程中调用wait()函数的时候 (1)假设其全部的子程序都还在执行,则堵塞 (2)假设一个子进程已终止.则等待父进程获取其终止状态. (3)假设没有子进程,则返回错误. ...
- UNIX环境高级编程(第三版)关于apue.h的用法
UNIX环境高级编程(第三版)中的例子用到apue.h这个头文件,但是书里面写的地址已经不能访问. 经过一番查找之后,找到如下解决方案: 1.到www.apuebook.com上下载第2版的源码,也可 ...
- UNIX环境高级编程——进程管理和通信(总结)
进程管理与通信 进程的管理 进程和程序的区别: 进程: 程序的一次执行过程 动态过程,进程的状态属性会发生变化 程序:存放在磁盘上的指令.数据的有序集合 是个文件,可直观看到 程序program ...
- UNIX环境高级编程——进程基本概述
一.什么是进程 从用户的角度来看进程是程序的一次执行过程.从操作系统的核心来看,进程是操作系统分配的内存.CPU时间片等资源的基本单位.进程是资源分配的最小单位.每一个进程都有自己独立的地址空间与执行 ...
- UNIX环境高级编程——进程关系
一.终端的概念 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),控制终端是保存在PCB中的信息,而我们 ...
- Unix环境高级编程—进程关系
终端登录 网络登录 进程组 getpgrp(void) setpgid(pid_t pid, pid_) 会话: 是一个或多个进程组的集合,通常由shell的管道将几个进程编成一组. setsid(v ...
- UNIX环境高级编程——进程环境
一.main函数 C程序总是从main函数开始.当内核执行C程序时,在调用main前先调用一个特殊的启动例程.可执行程序文件将此启动例程指定为程序的起始地址--这是由连接编译器设置的,而连接编译器则由 ...
随机推荐
- asp.net mvc 自定义模型绑定
在asp.net mvc的控制器中如果能够活用模型的自动绑定功能的话能够减少许多工作量.但是如果我们想要对前台传来的数据进行一些处理再绑定到模型上,该怎么做呢? 这里用一个绑定用户数据的小案例来讲解a ...
- python笔记7:优雅的python
7. 如何让python代码更 Pythonic : 1.变量交换: a, b = b, a 2.带有索引位置的集合遍历: colors = ['red', 'green', 'blue', 'yel ...
- 51nod 1050 循环数组最大子段和【环形DP/最大子段和/正难则反】
1050 循环数组最大子段和 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该 ...
- 2018年东北农业大学春季校赛 D wyh的迷宫【搜索】
链接:https://www.nowcoder.com/acm/contest/93/D来源:牛客网 题目描述 给你一个n*m的迷宫,这个迷宫中有以下几个标识: s代表起点 t代表终点 x代表障碍物 ...
- MySQL常见注意事项及优化
MySQL常见注意事项 模糊查询 like 默认是对name字段建立了索引 注意:在使用模糊查询的时候,当% 在第一个字母的位置的时候,这个时候索引是无法被使用的.但是% 在其他的位置的时候,索引是可 ...
- openshift scc解析
SCC使用UserID,FsGroupID以及supplemental group ID和SELinux label等策略,通过校验Pod定义的ID是否在有效范围内来限制pod的权限.如果校验失败,则 ...
- Codeforces 583 DIV2 GCD Table 贪心
原题链接:http://codeforces.com/problemset/problem/583/C 题意: 大概就是给你个gcd表,让你还原整个序列. 题解: 由$GCD(a,a)=a$,我们知道 ...
- 串口调试利器--Minicom配置及使用详解
因为现在电脑基本不配备串行接口,所以,usb转串口成为硬件调试时的必然选择.目前知道的,PL2303的驱动是有的,在dev下的名称是ttyUSB*. Minicom,是Linux下应用比较广泛的串口软 ...
- ios notification
apps can use local or push notifications to let people know when interesting things happen, such as: ...
- Copy Records From One Data Block To Another Data Block In Oracle Forms
In this tutorial you will learn to copy the records from one data block to another data block on sam ...