Chinaunix首页 | 论坛 | 博客
  • 博客访问: 249743
  • 博文数量: 51
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 575
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-22 13:49
文章分类
文章存档

2009年(1)

2008年(13)

2007年(7)

2006年(30)

我的朋友

分类:

2006-12-09 18:37:01

1、进程信息检测

1.1 getid族函数:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
pid_t getuid(void);
pid_t geteuid(void);
pid_t getgid(void);
pid_t getegid(void);


作用:
getpid——返回当前进程pid;
getppid——返回当前父进程pid;
getuid——返回运行当前进程用户的UID;
geteuid——返回运行当前进程用户的有效UID(一般跟uid相同,但是在例如在setUID之后就有效UID就变成root超级用户的UID)
getgid——返回运行当前进程用户所在组的GID;
getgid——返回运行当前进程用户所在组有效GID(setGID之后和GID不同);

1.2 getlogin:返回运行当前进程的用户登录名。

#include <unistd.h>
char *getlogin(void);


1.3 getpwnam:输入一个有效的用户名,返回一个记录了用户各种信息的passwd结构;

#include <pwd.h>
struct passwd *getpwnam(const char *name);


1.4 进程计时

#include <sys/times.h>
clock_t times(struct tms *buf);


times:返回系统启动后流逝至今的CPU时间,并设置输入的tms结构。tms结构包括: tms_utime(用户模式下流逝的CPU时间), tms_stime(内核/系统模式下流逝的CPU时间), tms_cutime(用户模式下流逝的子进程CPU时间), tms_cstime(内核/系统模式下流逝的子进程CPU时间)。

另有rusage结构有更多的资源利用信息。它可以用getusage这个函数设置。它们都在头文件中定义。

#include <sys/times.h>
#include <sys/resource.h>
#include <unistd.h>
int getrusage(int who, struct rusage *usage);


其中who为RUSAGE_SELF或者RUSAGE_CHILDREN,决定用当前进程还是子进程来设置rusage结构。

rusage结构包括timeval结构的ru_utime和ru_stime,以及记录存储IO情况的ru_minflt(引起RAM访问的次数)、ru_majflt(引起磁盘交换分区访问的次数), ru_nswap(读取的交换分区页数)等。

times调用返回的时间比getrusage要精确得多,但getrusage给出的资源利用信息要更详细。

2、进程的创建

2.1 system

#include <stdlib.h>
int system(const char *string);


system函数执行string所指的字符串。字符串一般为shell命令,可以包括选项和参数。例如

system("ls -l hello.c");


如果string为NULL该函数返回非零值,否则返回0;

2.2 fork

#include <unistd.h>
pid_t fork(void);


fork调用创建父进程的一个准确副本,包括相同的UID、EUID、GID、EGID、进程组(例如用|执行的shell命令管道就是一个进程组,用进程组PGID标识)、会话ID(会话由一个或多个进程或进程组构成,以惟一的session ID标识,创建一个shell就是创建一个shell会话)、环境变量、资源、打开的文件和共享内存段等。但是没有继承父进程的文件锁和pending未决信号。
fork执行成功后,在父进程中返回子进程的PID,在子进程中返回0。
fork调用要注意进程代码中不应有依赖父进程或子进程的代码,否则可能会引起竞态乃至系统死锁。

2.3 exec函数族

exec函数族包括6个函数:

#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, const char *envp[]);
int execv(const char *path, const char *argv[]);
int execve(const char *path, const char *argv[], const char *envp[];
int execvp(const char *file, const char *argv[]);


execl的第一个参数是包括路径的可执行文件,后面是列表参数,列表的第一个为命令path,接着为参数列表,最后必须以NULL结束。
execlp的第一个参数可以使用相对路径或者绝对路径。
execle,最后包括指向一个自定义环境变量列表的指针,此列表必须以NULL结束。
execv,v表示path后面接收的是一个向量,即指向一个参数列表的指针,注意这个列表的最后一项必须为NULL。
execve,path后面接收一个参数列表向量,并可以指定一个环境变量列表向量。
execvp,第一个参数可以使用相对路径或者绝对路径,v表示后面接收一个参数列表向量。

exec被调用时会替换调用它的进程,直接返回到调用它的进程的父进程,如果出错,返回-1并设置errno。

2.4 popen

popen使用FIFO管道执行外部程序。

#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);


popen通过type是r还是w确定command的输入/输出方向,r和w是相对command的管道而言的。r表示command从管道中读入,w表示command通过管道输出到它的stdout,popen返回FIFO管道的文件流指针。pclose则用于使用结束后关闭这个指针。

3. 进程控制

3.1 wait、waitpid

#include <sys/wait.h>
#include <sys/types.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);


这两个函数收集子进程的退出状态,以避免它成为僵尸进程。status为子进程的返回状态,0或-1。pid为要等待的子进程pid,可能的值有-1(等待任何PGID为PID的绝对值的子进程)、1(等待任何子进程)、0(等待任何PGID等于调用进程的子进程)、>0(pid等于PID的子进程)。option包括WNOHANG(没有子进程要退出时返回)和WUNTRACED(子进程没有要报告的状态而返回)。

3.2 中止进程的函数

进程被中止的原因包括:在main函数里面执行了return;执行了exit;执行了_exit;执行了abort;被一个信号中止。

#include <stdlib.h>
int exit(int status);


exit以status状态正常中止进程,如果有使用atexit登记了相关的处理程序,也可以执行。

_exit和exit不同的地方是它是在unistd.h中生命,会立刻中止调用它的进程,而且不会执行atexit登记的程序。

abort则立刻中止进程,如果系统允许还将发生core dump生成core文件,作为严重情况下使用。

使用kill函数是利用信号中止程序的一个例子。

#include <signal.h>
#include <sys/types.h>
int kill(pid_t pid, int sig);


pid为要杀死的进程,sig是要发送给该进程的信号,如果要杀死它,可以发送SIGKILL、SIGTERM、SIGQUIT。

3.3 信号

信号是硬件中断的软模拟,用信号量标识,为正整数,其宏定义在signal.h,均为SIG开头。

kill命令或者kill函数可以发送。与发送相对的则是捕获和处理信号。此外还有产生generate、递送deliver(信号将要被处理)、未决pending(信号已产生而未被递送的时间间隔)、忽略ignore、部署diposition(如何处理这个信号)等。多个信号可以用信号集合signal_set结构(定义在signal.h)表示。使用mask掩码可以阻塞信号以禁止它被递送。而SIGKILL和SIGSTOP是唯一两个不能被进程捕获和忽略的信号。

SIGALRM超时信号,通过alarm函数发送。

#include <unistd.h>
unsigned int alarm(unsigned int seconds);


调用alarm的进程在seconds时间到后会捕获到一个SIGALRM信号。

pause函数把调用它的进程挂起,直到捕获到一个信号。如果调用pause进程不能处理递送到的信号,则发生默认部署。pause在捕获到信号后返回,而信号被递送后的处理会在pause返回前执行。pause总返回-1并设置errno。

3.4 信号的创建和处理

#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(segset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);


sigemptyset:创建一个信号集合,该集合为空;
sigfillset:创建一个信号集合,该集合为满;
sigaddset:把信号signum添加到信号集合set中;
sigdelset:把信号signum从信号集合set中删除;
sigismember:测试信号signum是否在信号集合set中,如果是则返回1,否则返回0。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);


sigprocmask设置或者修改信号掩码,how为对set的可选处理,包括SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, NULL。

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);


sigaction为指定的信号signum设置一个信号处理器,结构sigaction描述了对该信号的部署。

#include <signal.h>
struct sigaction{
        void (*sa_handler)(int);
        sigset_t sa_mask;
        int sa_flags;
        void (*sa_restorer)(void);
}


sa_handler规定了signum中的信号产生后要调用的处理器或者函数,输入为一个int类型参数,返回一个void,或者也可以为SIG_DFL而引起signum的默认动作,SIG_IGN忽略sinnum;
sa_mask为要阻塞的信号掩码的集合;
sa_flags掩码修正sa_handler的行为,包括SA_NOCLDSTOP(忽略子进程的SIGSTOP等信号), SA_ONESHOT(登记的自定义信号处理器只执行一次,然后恢复信号的默认动作), SA_RESTART(让可重启的系统调用起作用), SA_NOMASK, SA_NODEFER。
sa_restorer:已经废弃不用。

#include <signal.h>
int sigpending(sigset_t *set);


sigpending检查是否有未决信号并设置到set中,如果挂起信号是为了执行某个操作,操作完成后可以用sigpending检查未决信号并处理之。否则简单接触阻塞就可以。

4. 进程的调度

#include <sched.h>
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p);
int sched_getscheduler(pid_t pid);
int sched_get_priority_max(int policy);
int sched_get_priority_min(int policy);
int getpriority(int which, int who);
int setpriority(int which, int who, int prio);
int nice(int inc);


sched_setscheduler和sched_getscheduler分别设置和取得与某个特定进程相关的策略和参数。策略policy包括SCHED_OTHER、SCHED_FIFO、SCHED_RR。后两者是用于特别看重时间的策略,会抢先于使用默认策略SHED_OTHER的进行执行;
sched_get_priority_max和sched_get_priority_min返回对于策略policy来说最大或最小的优先级。注意优先级的值越小,其级别越高;
setpriority设置进程(which=PRIO_PROCESS)、进程组(which=PRIO_PGRP)、用户(which=PRIO_USER)的动态优先级;
getpriority则返回匹配进程的最高优先级(最小值);
nice通过为当前的进程优先级增加一个inc而降低其优先级。
阅读(1930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~