UNIX环境高级编程---- 进程
来源:互联网 发布:des算法与rsa算法 编辑:程序博客网 时间:2024/04/28 22:38
进程是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
进程终止的8种方式
1) 从main返回
2) 调用exit
3) 调用_exit或_Exite
4) 最后一个线程从其启动例程返回
5) 最后一个线程调用pthread_exit
异常终止方式
6) 调用abort
7) 街道一个信号并终止
8) 最后一个线程对取消请求作出响应
_exit和_Exit函数立即进入内核,而exit则先执行一些清理处理(关闭标准I/O流等)然后进入内核,即为所有打开刘调用fclose函数。
atexit函数:注册用exit自动调用的函数,exit调用顺序与注册顺序相反。
#include <stdlib.h>
Int atexit(void (*func) (void));成功返回0, 出错返回-1
实例:
#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>void func1(void);void func2(void);int main(int argc, char **argv){if(atexit(func1) < 0){printf("atexit error:%s\n", strerror(errno));exit(1);}if(atexit(func2) < 0){printf("atexit error:%s\n", strerror(errno));exit(1);}printf("main function is called\n");exit(0);}void func1(void){printf("Function 1 is called\n");}void func2(void){printf("function 2 is called\n");}
运行结果:
进程标识符:每个进程都有一个非负整型表示的唯一进程ID,虽然进程ID是唯一的,但进程ID可以重用,当一个进程终止后其进程ID就可以再次使用,大多数UNIX系统实现延迟重用算法,使得赋予新进程的ID不同于最近终止进程所使用的ID。
ID为0的进程通常是调度进程,是内核的一部分,ID为1的是init进程,在自举过程结束时由内核调用,init进程决不会终止,它是一个普通进程的用户进程,但是它以超级用户特权运行。
获取进程ID函数;
#include <unistd.h>
pid_t getpid(void);返回值:调用进程的进程ID
pid_t getppid(void);返回值:调用进程的父进程ID
创建进程函数:
#include <unistd.h>
pid_t fork(void);返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1;
fork函数创建的新进程称为子进程,fork函数被调用一次,但返回两次,两次返回的唯一区别是子进程的返回值为0,而父进程的返回值则是子进程的进程ID,子进程和父进程继续执行fork调用之后的指令,子进程是父进程的副本,子进程获得父进程的数据空间,堆和栈的副本,也就是说子父进程不共享存储空间,子进程对变量所做的改变不影响父进程。
在一个进程终止时,内核会逐个检查所有活动进程,以判断它是否是正要终止进程的子进程,如果是,则将该进程的父进程ID改为1,以保证每个进程都有一个父进程,这就是init进程领养。
内核为每个终止子进程保存了一定量的信息,所有当终止进程的父进程调用wait或waitpid时可以得到这些信息,包括进程ID,进程的终止状态,记忆该进程是有的cpu时间总量,内核可以释放终止进程所使用的所有存储区,关闭其所有打开文件。
一个已经终止,但是其父进程尚未对其进行善后处理(wait,waitpid获取终止子进程有关信息,释放它仍占用资源)的进程被称为僵死进程。
wait ,waitpid 函数:
#include <sys.wait.h>
pit_t wait(int *statloc);
pit_t waitpid(pid_t pid, int *statloc, int options)两个函数返回值:若成功返回终止进程ID, 0, 若出错返回-1:
statloc是一个整型指针,如果statloc不是一个空指针,则终止进程的终止状态就存放在它所指向的单元内。如果不关心终止状态,则可将该参指定为空指针。
waitpid 函数的pid参数解释如下:
pid== -1 等待任何一个子进程,就这一方面而言waitpid与wait等效
pid>0 等待期进程ID与pid相等的子进程
pid==0 等待其组ID等于调用进程组ID的任一子进程
pid<0 等待其组ID等于pid绝对值的任一子进程
waitpid 函数options参数可以使我们进一步控制waitpid操作,此参数通常是0;
两个函数区别:
1)在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。
2)waitpid可以指定等待特定的子进程终止。
fork两次避免僵死进程:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/wait.h>#include <errno.h>int main(int argc, char **argv){pid_t pid;if((pid = fork()) < 0){printf("fork error:%s\n", strerror(errno));exit(1);}else if(pid == 0){if((pid = fork()) < 0){printf("fork error:%s\n", strerror(errno));exit(1);}else if(pid > 0){exit(0);}sleep(2);printf("second child, parent pid=%d\n", getppid());exit(0);}if(waitpid(pid, NULL, 0) != pid){printf("waitpid error:%s\n", strerror(errno));exit(1);}exit(0);}
运行结果:
exec函数:在用fork函数创建子进程后,子进程往往要调用一种exec函数以指向另一个程序,当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。
说是exec系统调用,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:
#include <unistd.h>
extern char **environ;
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 *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
Exec函数实例:
#include<unistd.h>main(){execlp(“ls”,”ls”,”-al”,”/etc/passwd”,(char *)0);}
- UNIX环境高级编程---- 进程
- unix环境高级编程-7-进程环境
- UNIX环境高级编程之进程环境
- 《UNIX环境高级编程》(进程环境)
- 《UNIX环境高级编程》--7进程环境
- unix环境高级编程-进程环境
- unix环境高级编程_精灵进程
- UNIX环境高级编程——进程
- 《UNIX环境高级编程》笔记--进程时间
- 《UNIX环境高级编程》笔记--进程组
- 《UNIX环境高级编程》笔记--守护进程
- Unix环境高级编程--进程控制
- Unix环境高级编程之进程控制
- Unix环境高级编程—进程关系
- unix环境高级编程-进程关系
- unix环境高级编程-守护进程
- unix环境高级编程-进程间通信
- 《UNIX环境高级编程》--8进程控制
- poj 1417 True Liars
- 结构体对齐
- Axis 简单入门实例
- GDT与LDT
- 调试的艺术——Debug技巧总结
- UNIX环境高级编程---- 进程
- 《编写可读代码的艺术》读书笔记(三)
- 一个程序的结构
- HDU 1198 Farm Irrigation
- 阿里面试题—最长公共子串算法
- hdu 4325 Flowers
- 变量。 数据类型。
- DWORD
- 手把手教你防止无线网络被盗用