Linux进程控制

以下内容全部摘自UNIX环境高级编程(第3版)

进程标识

除了进程ID,每个进程还有一些其他标识符。下列函数返回这些标识符。

#include <unistd.h>
pid_t getpid(void);                
返回值:调用进程的进程ID
pid_t getppid(void);
返回值:调用进程的父进程ID
uid_t getuid(void);
返回值:调用进程的实际用户ID
uid_t geteuid(void);
返回值:调用进程的有效用户ID
gid_t getgid(void);
返回值:调用进程的实际组ID
gid_t getegid(void);
返回值:调用进程的有效组ID

函数fork

一个现有的进程可以调用fork函数创建一个新进程。

#include <unistd.h>
pid_t fork(void);
返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1

函数vfork

vforkfork之间的一个区别是:vfork保证子进程先运行,在它调用execexit之后父进程才可能别调度运行,
当子进程调用这两个函数的任意一个时,父进程会恢复运行。
(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)
调用exit会先执行一些清理处理,_exit_Exit立即进入内核。

函数wait和waitpid

当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),
所以这种信号也是内核向父进程发的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。
对于这种信号的系统默认动作是忽略它。
现在需要知道的是调用waitwaitpid的进程可能会发生什么。
* 如果其所有子进程都还在运行,则阻塞。
* 如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程的终止状态立即返回。
* 如果它没有任何子进程,则立即出错返回。
如果进程由于接收到SIGCHLD信号而调用wait,我们期望wait会立即返回。但是如果在随机时间点调用wait,则进程可能会阻塞。

#include <sys/wait.h>
pid_t wait(int *staloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
两个函数返回值:若成功,返回进程ID;若出错,返回0或-1

这两个函数的参数statloc是一个整型指针。如果statloc不是一个空指针,则终止进程的终止状态就存放在它所指向的单元内。
如果不关心终止状态,则可将该参数指定为空指针。
对于waitpid函数中pid参数的作用解释如下

pid == -1 等待任一子进程。此种情况下,waitpidwait等效
pid > 0 等待进程ID与pid相等的子进程
pid == 0 等待组ID等于调用进程组ID的任一子进程。
pid < -1 等待组ID等于pid绝对值的任一子进程

waitpid函数返回终止子进程的进程ID,并将该子进程的终止状态存放在由staloc指向的存储单元中。
对于wait,其唯一的出错是调用进程没有子进程(函数调用被一个信号中断时,也可能返回另一种出错。)
但是对于waitpid,如果指定的进程或进程组不存在,或者参数pid指定的进程不是调用进程的子进程,都可能出错。
waitpidOptions

函数waitid

#include <sys/wait.h>
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
返回值:若成功,返回0;若出错,返回-1

该函数支持的idtype如下图
waitidIdtype
options参数是下图中各标志的按位或运算。这些标志指示调用者关注哪些状态变化。
waitidOptions

WNOHANG : Return immediately instead of blocking if there is no child exit status available.

WCONTINUEDWEXITEDWSTOPPED这3个常量之一必须在options参数中指定。
infop参数是指向siginfo结构的指针。该结构包含了造成子进程状态改变有关信号的详细信息。

函数wait3和wait4

允许内核返回由终止进程及其所有子进程使用的资源概况。

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>

pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage);
两个函数返回值:若成功,返回进程ID;若出错,返回-1

资源统计信息包括用户CPU时间总量、系统CPU时间总量、缺页次数、接收到信号的次数等。有关细节参阅
getrusage(2)手册页。

函数exec

#include <unistd.h>
int execl(const char *pathname, const char *arg0, ...  /* (char *)0 */ );
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, ... /* (char *)0, char *const envp[] */ );
int execve(const char *pathname, char *const argv[], char *const envp[] );
int execlp(const char *filename, const char *arg0, ...  /* (char *)0 */ );
int execvp(const char *filename, char *const argv[]);
int fexecve(int fd, char *const argv[], char *const envp[]);
7个函数返回值:若出错,返回-1;若成功,不返回

char arg0, char *arg1, …, char *argn, (char )0
这种语法显示地说明了最后一个命令行参数之后跟了一个空指针。如果用常量0来表示一个空指针,则必须将它强制转换为一个指针;
否则它将被解释为整型参数。如果一个整形数的长度与char *的长度不同,那么exec函数的实际参数将出错。

更改用户ID和更改组ID

可以用setuid函数设置实际用户ID和有效用户ID。与此类似,可以用setgid函数设置实际组ID和有效组ID

#include <unistd.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
两个函数返回值:若成功,返回0;若出错,返回-1

关于谁能更改ID有若干规则。现在先考虑更改用户ID的规则(关于用户ID我们所说明的一切都适用组ID)
* 若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID以及保存的设置用户ID(saved set-user-ID)设置为uid
* 若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置用户ID,则setuid只将有效用户ID设置为uid。不更改
实际用户ID和保存的设置用户ID
* 如果上面两个条件都不满足,则errno设置为EPERM,并返回-1

函数setreuid和setregid

功能是交换实际用户ID和有效用户ID的值

#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
两个函数返回值:若成功,返回0;若出错,返回-1

如若其中任一参数的值为-1,则表示相应的ID应当保持不变

函数seteuid和setegid

类似于setuidsetgid,但只更改有效用户ID和有效组ID

#include <unistd.h>
int seteuid(uid_t uid);
int setegid(gid_t gid);
两个函数返回值:若成功,返回0;若出错,返回-1

函数system

#include <stdlib.h>
int system(const char *cmdstring);
返回值:(见下)

因为system在其实现中调用了forkexecwaitpid,因此有3种返回值。
1. fork失败或者waitpid返回除EINTR之外的出错,则system返回-1,并且设置errno以指示错误类型
2. 如果exec失败(表示不能执行shell),则其返回值如同shell执行了exit(127)一样。
3. 否则所有3个函数(forkexecwaitpid)都成功,那么system的返回值是shell的终止状态,其格式已在waitpid中说明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值