Linux系统调用(八)—进程控制
1.
名称:: getpid
功能: 获得进程id.
头文件: #include <unistd.h>
函数原形: pid_t getpid(void);
参数: 无
返回值: 进程id.
每个进程都有一个非负整数表示的唯一进程id。系统中有一些专用的进程该进程是内核的一部分,它并不执行任何磁盘上的程序。因此也被称为系统进程。
进程1通常是init进程,在自举过程完成时有内核调用。此进程负责在自举内核后启动一个UNIX系统。init通常读与系统有关的初始化文件(/ect/re*文件或/ect/inittab文件,以及/ect/init.d中的文件),并将系统引导到一个状态。但要注意init并不是一个系统进程,它是一个普通用户进程,但是它以超级用户特权运行。
2.
名称:: getppid
功能: 获得进程的父进程id
头文件: #include <unistd.h>
函数原形: pid_t getppid(void);
参数: 无
返回值: 父进程id.
3.
名称:: getuid/geteuid
功能: 获得调用进程用户的实际用户id和有效用户id.
头文件: #include <unistd.h>
函数原形: uid_t getuid(void);
uid_t geteuid(void)
参数: 无
返回值: 用户id.
3.
名称:: getgid/getegid
功能: 获得调用进程用户的实际组id和有效组id.
头文件: #include <unistd.h>
函数原形: gid_t getgid(void);
gid_t getegid(void);
参数: 无
返回值: 用户组id.
与一个进程相关联的用户id用6个或更多,他们是:实际用户id 实际组id 有效用户id 有效组id 保存的设置用户id 保存的设置组id
实际用户id和实际组id标识我们究竟是谁。这两个字段在登陆时取自口令文件中的登陆项。通常,在一个登陆会话间这些值并不改变,但是超级用户进程又方法改变它们。
有效用户id和有效组id以及附加组id决定了我们的文件访问权限。
保存的设置用户id和保存的设置组id在执行一个程序是包含了有效用户id和有效组id的副本。
通常有效用户id等于实际用户id,有效组id等于实际组id。它们不同的情况通过发生在变更用户权限,但是不切换用户的情况下。
下面的程序打印和进程id和用户id
- #include <unistd.h>
- main()
- {
- printf(“pid:%dn”,getpid());
- printf(“ppid:%dn”,getppid());
- printf(“uid:%dn”,getuid());
- printf(“euid:%dn”,geteuid());
- printf(“gid:%dn”,getgid());
- printf(“egid:%d”,getegid());
- }
复制代码
4.
名称:: fork
功能: 创建一个进程
头文件: #include <unistd.h>
#include <sys/types.h>
函数原形: pid_t fork(void);
参数: 无
返回值: 子进程返回0,父进程返回子进程id,出错返回1。
由fork创建的进程成为子进程,fork函数被调用一次,但返回两次。两次返回唯一区别是子进程返回的是0,父进程返回的是子进程的id.子进程是父进程的副本子进程获得父进程数据空间、堆和栈的副本。父、子进程并不共享这些存储空间,父、子进程只共享正文段。由于在fork之后经常跟着exec,所以现在很多实现并不执行一个父进程数据段、堆和栈的完全复制,它们采用一种叫做写时复制技术。
fork有两种用法:
(1) 一个父进程希望复制自己,使父、子进程同时执行不同的代码段。
(2) 一个进程要执行一个不同的程序。这对shell是常见的情况。
下面是fork函数的一个例子。
- #include <unistd.h>
- #include <sys/types.h>
- int main()
- {
- pid_t pid;
- if((pid=fork())==0)
- printf(“I’am child,my id is %d,my father id is %d”,getpid(),getppid()”);
- else
- printf(“I’am father, my id is %d,my child id is %d”,getpid(),pid);
- }
复制代码
5.
名称:: vfork
功能: 创建一个进程
头文件: #include <unistd.h>
#include <sys/types.h>
函数原形: pid_t vfork(void);
参数: 无
返回值: 进程id.
vfork与fork一样都创建一个进程,但是它并不是将父进程的地址空间完全复制到子进程中,在子进程调用exec或exit之前,它在父进程的空间中运行。这要就提高了效率。
vfork和fork的另一个区别是:vfork保证子进程先运行,在它调度exex或exit后父进程才可能被调度运行。
6.
名称:: wait/waitpid
功能: 等待一个进程的终止
头文件: #include <sys/types.h>
#include <sys/wait.h>
函数原形: pid_t wait(int *statloc);
pid_t waitpid(pid_t pid,int *statloc,int options);
参数: statloc 指向存放终止状态单元的指针
pid options 控制wait的操作
返回值: 若成功返回进程id,若出错返回0。
两个函数都是的功能都是获取子进程终止状态,但在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。
waitpid并不等待在其调用之后的第一个终止进程,它有若干个选项,可以控制它所等待的进程。
如果一个之进程已经终止,并且是一个僵尸进程,则wait立即返回并取得该子进程的状态,否则wait使其调用者阻塞直到一个子进程终止。
对于waitpid函数的参数pid的解释如下:
pid==-1 等待任一子进程。
pid>0 等待其进程与pid相等的子进程。
pid<-1 等待其组id等于pid绝对值的任一子进程。
options参数使我们能进一步控制waitpid的操作。此参数可以是0,或者是:
WCONTINUED 用于作用控制
WNOHANG 若pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回值为0。
WUNTRACED 用于作业控制。
下面是wait的一个例子。
- #include <stdio.h>
- #include <sys/wait.h>
- #include <sys/types.h>
- #include <unistd.h>
- main()
- {
- pid_t pid;
- pid_t cpid;
- if((pid=fork())==0)
- {
- printf(“I’m a chile,my id is %dn”,getpid());
- sleep(1);
- exit(1);
- }
- else
- {
- printf(“I’m a father,my id is %dn”,getpid());
- if(cpid=wait(NULL)!=-1)
- printf(“I catch a child is %dn”,cpid);
- }
- }
复制代码运行结果是:
I’m child,my id is 16557
I’m father,my id is 16556
I catch a child is 16557
程序先打印子、父进程的id.然后子进程调用sleep函数,这时父进程阻塞,直到子进程调用exit终止退出,父进程获得子进程终止信息。
7.
名称:: waitid
功能: 等待一个进程的终止
头文件: #include <sys/types.h>
#include <sys/wait.h>
函数原形: int waited(idtype_t idtype,id_t id,siginfo_t *infop,int options);
参数:
返回值: 若成功返回进程0,若出错返回-1。
与waitpid相似,waitid允许一个进程指定要等待的子进程。但它使用单独的参数表示要等待的子进程的类型,而不是将此与进程Id或进程组id组合成一个参数。
8.
名称:: wait3/wait4
功能: 等待一个进程的终止
头文件: #include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
函数原形: pid_t wait3(int *stacloc,int options,struct rusage *rusage);
pid_t wait4(pid_t pid,int *statloc,int options,struct rusage *rusage);
参数:
返回值: 若成功返回进程id ,若出错返回-1。
wait3,wait4的功能更强大,这与附加参数rusage有关。该函数要求内核返回由终止进程及其所有子进程使用的资源汇总。资源统计信息包括用户CPU时间总量,系统CPU时间总量,页面出错次数,接收到信号的次数等。
9.
名称:: exec
功能: 等待一个进程的终止
头文件: #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,…,char *const envp[]);
int execv(const char *fath,char *const argv[]);
int execvp(const char *file,char *const argv[]);
int execve(const char *file,char *const argv[],char *const envp[]);
参数: path 路径名
file 文件名
arg 单独的命令参数,以NULL结束。
argv 指向命令参数列表
envp 指向环境字符串指针数组的指针
返回值: 若出错返回-1。若成功不返回值
字母p表示该函数取filename作为参数,并且用PATH环境变量寻找可执行文件。字母l表示该函数去一个参数表,它与字符v互斥。v表示该函数去一个argv[]矢量。最后,字母e表示该函数取envp[]数组,而不使用当前环境。
在执行exec前后实际用户I
D和实际组ID保持不变,而有效ID是否改变则取决于所执行程序文件的设置用户ID位和设置组ID位是否设置。如果新程序的设置用户ID位已设置,则有效用户ID变成程序文件所以者的ID,否则有效用户ID不变。对组ID的处理方式与此相同。
- #include <sys/types.h>
- #include <sys.wait.h>
- #include <unistd.h>
- int main(int argc,char *argv[])
- {
- pid_t pid;
- if((pid=fork())==0)
- execl(argv[1],argv[2],argv[3],(char*)0);
- else
- waitpid(pid,NULL,0);
- }
复制代码
10.
名称:: setuid/setgid
功能: 更改用户ID和组ID
头文件: #include <unistd.h>
函数原形: int setuid(uid_t uid);
int setgid(gid_t gid);
参数: uid 用户id
gid 组id
返回值: 若成功返回进程0,若出错返回-1。
11.
名称:: setreuid/setregid
功能: 交换实际用户ID和有效用户ID.
头文件: #include <unistd.h>
函数原形: int setreuid(uid_t ruid,uid_t euid);
int setregid(gid_t rgid,uid_t egid);
参数: euid 有效用户id
ruid 实际用户id
egid 有效组id
rgid实际组id
返回值: 若成功返回进程0,若出错返回-1。
12.
名称:: seteuid/setegid
功能: 更改用户有效ID和有效组ID
头文件: #include <unistd.h>
函数原形: int setuid(uid_t uid);
int setgid(gid_t gid);
参数: uid 用户id
gid 组id
返回值: 若成功返回进程0,若出错返回-1。
13.
名称:: system
功能:
头文件: #include <unistd.h>
函数原形: int setuid(uid_t uid);
int setgid(gid_t gid);
参数: uid 用户id
gid 组id
返回值: 若成功返回进程0,若出错返回-1。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论