C语言--进程相关函数
获取进程ID
头文件:#include <unistd.h>
pid_t getpid(void)
:获取进程IDpid_t getppid(void)
:获取父进程IDpid_t getuid(void)
:获取用户IDpid_t geteuid(void)
:获取有效用户IDpid_t getgid(void)
:获取组IDpid_t getegid(void)
:获取有效组ID
其中pid_t
类型本质是无符号整型,定义在头文件#include <types.h>
,在不同的平台上上可能是typedef int pid_t
或是typedef long pid_t
示例
#include <stdio.h>
#include <unistd.h>
int main() {
printf("the process id is [%d]\n", getpid());
printf("the parent process id is [%d]\n", getppid());
printf("the user id is [%d]\n", getuid());
printf("the effective id is [%d]\n", geteuid());
printf("the group id is [%d]\n", getgid());
printf("the effective group id is [%d]\n", getegid());
return 0;
}
结果
the process id is [2749]
the parent process id is [721]
the user id is [1000]
the effective id is [1000]
the group id is [1000]
the effective group id is [1000]
设置进程ID
- setuid()
头文件:#include <unistd.h>
;
声明:int setuid(uid_t uid)
;
功能:修改用户ID(无论是否有效),参数uid
表示改变后的新ID;
返回值:如果成功修改当前进程的用户ID,返回0;否则返回-1; - seteuid()
头文件:#include <unistd.h>
;
声明:int seteuid(uid_t uid)
;
功能:修改有效用户的ID,参数uid
表示改变后的新ID;
返回值:如果成功修改当前进程的有效用户ID,返回0;否则返回-1; - setgid()
头文件:#include <unistd.h>
;
声明:int setgid(gid_t gid)
;
功能:修改组ID(无论是否有效),参数gid
表示改变后的ID;
返回值:如果修改成功返回0;否则返回-1; - setegid()
头文件:#include <unistd.h>
声明:int setegid(gid_t gid)
;
功能:修改有效组ID,参数gid
表示改变后的ID;
返回值:如果修改成功返回0,否则返回-1;
创建进程
- fork()
头文件:#include <unistd.h>
声明:pid_t fork(void)
;
功能:创建一个新进程,得到一个新的可用进程ID。并将父进程的数据段和堆栈段复制到子进程的进程空间,并且和父进程共享代码段(代码段是只读的,不存在修改的问题)
返回值:
父进程中,返回新创建的子进程的进程ID
子进程中,返回值为0
出现错误,返回负值
fork()出错的原因:当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN
系统内存不足,这时errno的值被设置为ENOMEM
注意:创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。
示例:
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t fpid;
int count = 0;
fpid = fork();
if (fpid < 0) {
printf("ERROR IN FORK!");
} else if (fpid == 0) {
printf("[ %d ] this is child process\n", getpid());
count++;
} else {
printf("[ %d ] this is parent process\n", getpid());
count++;
}
printf("%d\n", count);
return 0;
}
结果
[ 2812 ] this is parent process
1
[ 2813 ] this is child process
1
当程序执行到fpid = fork()
后就是出现两个进程,分别是父进程和子进程,可以说fork()
就是将当前进程的情况拷贝了一份,执行相同的代码段,通过变量fpid
来控制父子进程实现不同功能,达到想要的效果。
- wait()
头文件:<sys/types.h>、<unistd.h>
声明:pid_t wait(int* status)
;
功能: 使进程进入阻塞状态,直到任意子进程结束或者该进程接受到信号为止;如果该进程没有子进程,或子进程已经结束,wait()
会立即返回;参数status
为空时表示忽略子进程退出时的状态,不为空表示保存子进程退出时的状态;[1]
返回值:如果成功,返回被收集的子进程的进程ID;如果没有子进程,调用会失败,返回-1,同时errno被置为ECHILD - waitpid()
头文件:#include <sys/types.h
声明:pid_t waitpid(pid_t pid, int* status, int options)
;
功能:
参数:
pid
:
- 传入大于0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去
- 传入等于-1时,等待任意子进程(作用与wait()相同)
- 传入等于0时,等待其组ID等于调用进程的组ID的任意子进程
- 传入小于-1时,等待其组ID等于PID的绝对值的任意子进程
status
: 为空时表示忽略子进程退出时的状态,不为空表示保存子进程退出时的状态options
:
- 传入等于0时,同wait()阻塞父进程
- 传入为
WNOHANG
,若由PID指定的子进程并不立即可用,则waitpid不会被阻塞,此时返回值为0,子进程结束时返回子进程PID- 传入为
WUNTRACED
,涉及跟踪调试,使用极少,不多赘述
退出进程
- exit()
头文件:#include <stdlib.h>
声明:void exit(int status)
功能:使进程终止,并清除缓冲区;参数status是该程序的退出状态,如果正常退出参数为0;异常退出为非0
返回值:无返回值 - _exit()
头文件:#include <unistd.h>
声明:void _exit(int status)
功能: 使进程终止,不清除缓冲区
父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。 ↩︎