Linux进程函数详解
1. atexit
(设置程序正常结束前调用的函数)
相关函数 _exit,exit,on_exit
表头文件 #include
定义函数 int atexit (void (*function)(void));
函数说明 atexit() 用来设置一个程序正常结束前调用的函数。当程序通过调用 exit()或从 main 中返回时,参数 function 所指定的函数会先被调用,然后才真正由 exit() 结束程序。
返回值 如果执行成功则返回 0,否则返回 - 1,失败原因存于 errno 中。
- #include < stdlib.h > void my_exit(void) {
- printf("before exit() ! \n");
- }
- main() {
- atexit(my_exit);
- exit(0);
- }
执行 before exit()!
2. execl(执行文件)
相关函数 fork,execle,execlp,execv,execve,execvp
表头文件 #include
定义函数 int execl(const char * path,const char * arg,....);
函数说明 execl() 用来执行参数 path 字符串所代表的文件路径,接下来的参数代表执行该文件时传递过去的 argv(0)、argv[1]……,最后一个参数必须用空指针 (NULL) 作结束。
返回值 如果执行成功则函数不会返回,执行失败则直接返回 - 1,失败原因存于 errno中。
- #include < unistd.h > main() {
- execl(" / bin / ls", "ls", " - al", " / etc / passwd", (char * ) 0);
- }
执行 /* 执行 / bin/ls -al /etc/passwd */-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
3. execlp(从 PATH 环境变量中查找文件并执行)
相关函数 fork,execl,execle,execv,execve,execvp
表头文件 #include
定义函数 int execlp(const char * file,const char * arg,……);
函数说明 execlp() 会从 PATH 环境变量所指的目录中查找符合参数 file 的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的 argv[0]、argv[1]……,最后一个参数必须用空指针 (NULL) 作结束。
返回值 如果执行成功则函数不会返回,执行失败则直接返回 - 1,失败原因存于 errno 中。
错误代码 参考 execve()。
范例
- /* 执行ls -al /etc/passwd execlp()会依PATH 变量中的/bin找到/bin/ls */
- #include < unistd.h > main() {
- execlp("ls", "ls", " - al", " / etc / passwd", (char * ) 0);
- }
执行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
4. execv(执行文件)
相关函数 fork,execl,execle,execlp,execve,execvp
表头文件 #include
定义函数 int execv (const char * path, char * const argv[]);
函数说明 execv() 用来执行参数 path 字符串所代表的文件路径,与 execl() 不同的地方在于 execve() 只需两个参数,第二个参数利用数组指针来传递给执行文件。
返回值 如果执行成功则函数不会返回,执行失败则直接返回 - 1,失败原因存于 errno中。
错误代码 请参考 execve()。
范例 /* 执行 / bin/ls -al /etc/passwd */
- #include < unistd.h > main() {
- char * argv[] = {"ls",
- " - al",
- " / etc / passwd",
- (char * )
- }
- };
- execv(" / bin / ls", argv);
- }
执行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
5. execve(执行文件)
相关函数 fork,execl,execle,execlp,execv,execvp
表头文件 #include
定义函数 int execve(const char * filename,char * const argv[],char * const envp[]);
函数说明 execve() 用来执行参数 filename 字符串所代表的文件路径,第二个参数系利用数组指针来传递给执行文件,最后一个参数则为传递给执行文件的新环境变量数组。
返回值 如果执行成功则函数不会返回,执行失败则直接返回 - 1,失败原因存于 errno中。
错误代码 EACCES1. 欲执行的文件不具有用户可执行的权限。2. 欲执行的文件所属的文件系统是以 noexec 方式挂上。3. 欲执行的文件或 script 翻译器非一般文件。EPERM1. 进程处于被追踪模式,执行者并不具有 root 权限,欲执行的文件具有 SUID 或 SGID位。2. 欲执行的文件所属的文件系统是以 nosuid 方式挂上,欲执行的文件具有 SUID 或 SGID位元,但执行者并不具有 root 权限。E2BIG 参数数组过大ENOEXEC 无法判断欲执行文件的执行文件格式,有可能是格式错误或无法在此平台执行。EFAULT 参数 filename 所指的字符串地址超出可存取空间范围。ENAMETOOLONG 参数 filename 所指的字符串太长。ENOENT 参数 filename 字符串所指定的文件不存在。ENOMEM 核心内存不足ENOTDIR 参数 filename 字符串所包含的目录路径并非有效目录EACCES 参数 filename 字符串所包含的目录路径无法存取,权限不足ELOOP 过多的符号连接ETXTBUSY 欲执行的文件已被其他进程打开而且正把数据写入该文件中EIO I/O 存取错误ENFILE 已达到系统所允许的打开文件总数。EMFILE 已达到系统所允许单一进程所能打开的文件总数。EINVAL 欲执行文件的 ELF 执行格式不只一个 PT_INTERP 节区EISDIR ELF 翻译器为一目录ELIBBAD ELF 翻译器有问题。
范例
- #include < unistd.h > main() {
- char * argv[] = {"ls",
- " - al",
- " / etc / passwd",
- (char * ) 0
- };
- char * envp[] = {"PATH = /bin",0}
- execve("/bin / ls",
- argv,
- envp);
- }
执行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
6. execvp(执行文件)
相关函数 fork,execl,execle,execlp,execv,execve表头文件 #include定义函数 int execvp(const char *file ,char * const argv []);函数说明 execvp() 会从 PATH 环境变量所指的目录中查找符合参数 file 的文件名,找到后便执行该文件,然后将第二个参数 argv 传给该欲执行的文件。返回值 如果执行成功则函数不会返回,执行失败则直接返回 - 1,失败原因存于 errno 中。错误代码 请参考 execve()。范例 /* 请与 execlp()范例对照 */
- #include < unistd.h > main() {
- char * argv[] = {"ls",
- " - al",
- " / etc / passwd",
- 0
- };
- execvp("ls", argv);
- }
执行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
7. exit(正常结束进程)
相关函数 _exit,atexit,on_exit表头文件 #include定义函数 void exit(int status);函数说明 exit() 用来正常终结目前进程的执行,并把参数 status 返回给父进程,而进程所有的缓冲区数据会自动写回并关闭未关闭的文件。返回值范例 参考 wait()
8. _exit(结束进程执行)
相关函数 exit,wait,abort表头文件 #include定义函数 void _exit(int status);函数说明 _exit() 用来立刻结束目前进程的执行,并把参数 status 返回给父进程,并关闭未关闭的文件。此函数调用后不会返回,并且会传递 SIGCHLD 信号给父进程,父进程可以由 wait 函数取得子进程结束状态。返回值附加说明 _exit()不会处理标准 I/O 缓冲区,如要更新缓冲区请使用 exit()。
9. vfork(建立一个新的进程)
相关函数 wait,execve表头文件 #include定义函数 pid_t vfork(void);函数说明 vfork() 会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量、已打开的文件代码、工作目录和资源限制等。Linux 使用 copy-on-write(COW) 技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作,由于这些继承的信息是复制而来,并非指相同的内存空间,因此子进程对这些变量的修改和父进程并不会同步。此外,子进程不会继承父进程的文件锁定和未处理的信号。注意,Linux 不保证子进程会比父进程先执行或晚执行,因此编写程序时要留意死锁或竞争条件的发生。返回值
如果 vfork() 成功则在父进程会返回新建立的子进程代码 (PID),而在新建立的子进程中则返回 0。如果 vfork 失败则直接返回 - 1,失败原因存于 errno 中。错误代码 EAGAIN 内存不足。ENOMEM 内存不足,无法配置核心所需的数据结构空间。
范例
- #include < unistd.h > main() {
- if (vfork() = =0) {
- printf("This is the child process / n");
- } else {
- printf("This is the parent process / n");
- }
- }
执行 this is the parent process this is the child process
10. getpgid(取得进程组识别码)
相关函数 setpgid,setpgrp,getpgrp表头文件 #include定义函数 pid_t getpgid(pid_t pid);函数说明 getpgid() 用来取得参数 pid 指定进程所属的组识别码。如果参数 pid 为 0,则会取得目前进程的组识别码。返回值 执行成功则返回组识别码,如果有错误则返回 - 1,错误原因存于 errno 中。错误代码 ESRCH 找不到符合参数 pid 指定的进程。范例 /* 取得 init 进程(pid=1)的组识别码 */#includemian(){printf("init gid = %d/n",getpgid(1));}执行 init gid = 0getpgrp(取得进程组识别码)相关函数 setpgid,getpgid,getpgrp表头文件 #include定义函数 pid_t getpgrp(void);函数说明 getpgrp() 用来取得目前进程所属的组识别码。此函数相当于调用 getpgid(0);返回值 返回目前进程所属的组识别码。范例 #includemain(){printf("my gid =%d/n",getpgrp());}执行 my gid =29546getpid(取得进程识别码)相关函数 fork,kill,getpid表头文件 #include定义函数 pid_t getpid(void);函数说明 getpid()用来取得目前进程的进程识别码,许多程序利用取到的此值来建立临时文件,以避免临时文件相同带来的问题。返回值 目前进程的进程识别码范例 #includemain(){printf("pid=%d/n",getpid());}执行 pid=1494 /* 每次执行结果都不一定相同 */getppid(取得父进程的进程识别码)相关函数 fork,kill,getpid表头文件 #include定义函数 pid_t getppid(void);函数说明 getppid() 用来取得目前进程的父进程识别码。返回值 目前进程的父进程识别码。范例 #includemain(){printf("My parent'pid =%d/n",getppid());}执行 My parent pid =463getpriority(取得程序进程执行优先权)相关函数 setpriority,nice表头文件 #include#include定义函数 int getpriority(int which,int who);函数说明 getpriority() 可用来取得进程、进程组和用户的进程执行优先权。参数 which 有三种数值,参数 who 则依 which 值有不同定义which who 代表的意义PRIO_PROCESS who 为进程识别码PRIO_PGRP who 为进程的组识别码PRIO_USER who 为用户识别码此函数返回的数值介于 - 20 至 20 之间,代表进程执行优先权,数值越低代表有较高的优先次序,执行会较频繁。返回值 返回进程执行优先权,如有错误发生返回值则为 - 1 且错误原因存于 errno。附加说明 由于返回值有可能是 - 1,因此要同时检查 errno 是否存有错误原因。最好在调用次函数前先清除 errno 变量。错误代码 ESRCH 参数 which 或 who 可能有错,而找不到符合的进程。EINVAL 参数 which 值错误。nice(改变进程优先顺序)相关函数 setpriority,getpriority表头文件 #include定义函数 int nice(int inc);函数说明 nice() 用来改变进程的进程执行优先顺序。参数 inc 数值越大则优先顺序排在越后面,即表示进程执行会越慢。只有超级用户才能使用负的 inc 值,代表优先顺序排在前面,进程执行会较快。返回值 如果执行成功则返回 0,否则返回 - 1,失败原因存于 errno 中。错误代码 EPERM 一般用户企图转用负的参数 inc 值改变进程优先顺序。on_exit(设置程序正常结束前调用的函数)相关函数 _exit,atexit,exit表头文件 #include定义函数 int on_exit(void (* function)(int, void*),void *arg);函数说明 on_exit() 用来设置一个程序正常结束前调用的函数。当程序通过调用 exit() 或从 main 中返回时,参数 function 所指定的函数会先被调用,然后才真正由 exit() 结束程序。参数 arg 指针会传给参数 function 函数,详细情况请见范例。返回值 如果执行成功则返回 0,否则返回 - 1,失败原因存于 errno 中。附加说明范例 #includevoid my_exit(int status,void *arg){printf("before exit()!/n");printf("exit (%d)/n",status);printf("arg = %s/n",(char*)arg);}main(){char * str="test";on_exit(my_exit,(void *)str);exit(1234);}执行 before exit()!exit (1234)arg = testsetpgid(设置进程组识别码)相关函数 getpgid,setpgrp,getpgrp表头文件 #include定义函数 int setpgid(pid_t pid,pid_t pgid);函数说明 setpgid() 将参数 pid 指定进程所属的组识别码设为参数 pgid 指定的组识别码。如果参数 pid 为 0,则会用来设置目前进程的组识别码,如果参数 pgid 为 0,则会以目前进程的进程识别码来取代。返回值 执行成功则返回组识别码,如果有错误则返回 - 1,错误原因存于 errno 中。错误代码 EINVAL 参数 pgid 小于 0。EPERM 进程权限不足,无法完成调用。ESRCH 找不到符合参数 pid 指定的进程。setpgrp(设置进程组识别码)相关函数 getpgid,setpgid,getpgrp表头文件 #include定义函数 int setpgrp(void);函数说明 setpgrp() 将目前进程所属的组识别码设为目前进程的进程识别码。此函数相当于调用 setpgid(0,0)。返回值 执行成功则返回组识别码,如果有错误则返回 - 1,错误原因存于 errno 中。setpriority(设置程序进程执行优先权)相关函数 getpriority,nice
表头文件 #include#include
定义函数 int setpriority(int which,int who, int prio);
函数说明 setpriority() 可用来设置进程、进程组和用户的进程执行优先权。参数which 有三种数值,参数 who 则依 which 值有不同定义which who 代表的意义PRIO_PROCESS who 为进程识别码PRIO_PGRP who 为进程的组识别码PRIO_USER who 为用户识别码参数 prio 介于 - 20 至 20 之间。代表进程执行优先权,数值越低代表有较高的优先次序,执行会较频繁。此优先权默认是 0,而只有超级用户(root)允许降低此值。
返回值 执行成功则返回 0,如果有错误发生返回值则为 - 1,错误原因存于 errno。ESRCH 参数 which 或 who 可能有错,而找不到符合的进程EINVAL 参数 which 值错误。EPERM 权限不够,无法完成设置EACCES 一般用户无法降低优先权
system(执行 shell 命令)相关函数 fork,execve,waitpid,popen
表头文件 #include
定义函数 int system(const char * string);
函数说明 system() 会调用 fork() 产生子进程,由子进程来调用 / bin/sh-c string 来执行参数 string 字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system() 期间 SIGCHLD 信号会被暂时搁置,SIGINT 和 SIGQUIT 信号则会被忽略。
返回值 如果 system() 在调用 / bin/sh 时失败则返回 127,其他失败原因返回 - 1。若参数string 为空指针 (NULL),则返回非零值。如果 system() 调用成功则最后会返回执行 shell命令后的返回值,但是此返回值也有可能为 system() 调用 / bin/sh 失败所返回的 127,因此最好能再检查 errno 来确认执行成功。
附加说明 在编写具有 SUID/SGID 权限的程序时请勿使用 system(),system() 会继承环境变量,通过环境变量可能会造成系统安全的问题。
范例 #includemain(){system("ls -al /etc/passwd /etc/shadow");}
执行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd-r--------- 1 root root 572 Sep 2 15 :34 /etc/shadow
wait(等待子进程中断或结束)相关函数 waitpid,fork
表头文件 #include#include
定义函数 pid_t wait (int * status);
函数说明 wait() 会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用 wait() 时子进程已经结束,则 wait() 会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则
参数 status 可以设成 NULL。子进程的结束状态值请参考 waitpid()。
返回值 如果执行成功则返回子进程识别码 (PID),如果有错误发生则返回 - 1。失败原因存于 errno 中。
附加说明
范例 #include#include#include#includemain(){pid_t pid;int status,i;if(fork()= =0){printf("This is the child process .pid =%d/n",getpid());exit(5);}else{sleep(1);printf("This is the parent process ,wait for child.../n";pid=wait(&status);i=WEXITSTATUS(status);printf("child's pid =%d .exit status=^d/n",pid,i);}}
执行 This is the child process.pid=1501This is the parent process .wait for child...child's pid =1501,exit status =5
waitpid(等待子进程中断或结束)相关函数 wait,fork
表头文件 #include#include
定义函数 pid_t waitpid(pid_t pid,int * status,int options);
函数说明 waitpid() 会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用 wait() 时子进程已经结束,则 wait() 会立即返回子进程结束状态值。子进程的结束状态值会由参数 status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码,其他数值意义如下:pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。pid=-1 等待任何子进程,相当于 wait()。pid=0 等待进程组识别码与目前进程相同的任何子进程。pid>0 等待任何子进程识别码为 pid 的子进程。参数 option 可以为 0 或下面的 OR 组合WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。子进程的结束状态返回后存于 status,底下有几个宏可判别结束情况WIFEXITED(status) 如果子进程正常结束则为非 0 值。WEXITSTATUS(status) 取得子进程 exit() 返回的结束代码,一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。WIFSIGNALED(status) 如果子进程是因为信号而结束则此宏值为真WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED 来判断后才使用此宏。WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先用 WIFSTOPPED 来判断后才使用此宏。
返回值 如果执行成功则返回子进程识别码 (PID),如果有错误发生则返回 - 1。失败原因存于 errno 中。
范例 参考 wait()。
来源: http://lib.csdn.net/article/linux/49858