进程是资源分配的最小单位
查看进程的一些命令:
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ps axj有父进程与子进程关系,还有组进程。
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
进程的三种状态:运行态,就绪态,阻塞态。
内核调用C启动例程,C启动例程是一段已经编写好的代码。由C启动例程执行主函数main,结束时回到C启动例程,
进程结束有8种情况,5种正常终止,3种异常终止
1.从main返回
2.调用exit
3.调用_exit或者_Exit
4.最后一个线程从其启动例程返回
5.最后一个线程调用pthread_exit
异常:
1.调用abort
2.接到一个信号并终止
3.最后一个线程对取消请求做出响应
main函数可以利用return返回数值到C启动例程中,由C启动例程调用exit函数,exit在进行一些清理工作之后,调用_exit或者_Exit返回内核。
main函数还可以直接在函数内调用_exit或者_Exit,回到内核。
用户函数中直接调用_exit或者_Exit。
用户函数调用exit。
exit与_exit的不同:
exit是库函数,_exit是系统调用函数。
exit在调用_exit函数之前需要调用终止处理函数(atexit),和标准io缓存区清理函数。
_exit什么都不做,直接终止。
#include <stdio.h>
int main(void)
{
printf("hello world");
exit(0);//会打印hello world
return 0;//会打印hello world
_exit(0);//不会打印出 hello world
}
进程的基本环境:
环境表:每个进程都有一张环境表,是由父进程复制给子进程的,存储在全局变量char **environ,
environ环境表指针指向每一个环境变量组成的字符串对应的指针数组的起始地址。
获取和设置环境变量:
char *getenv(const char *name);
int *setenv(const char *name, const char *value, int overwrite);
#include <stdio.h>
extern char **environ;
int main(int argc, char *argv[])
{
int i;
for(i = 0; environ[i]; i++)
puts(environ[i]);//得到每一个环境变量
printf("取得PATH的值:");
printf("%s\n", getenv("PATH"));
printf("修改PATH的值:");
setenv("PATH", "./", 1);
printf("%s\n", getenv("PATH"));
exit(0);
}
int setjmp(jmp_buf env);
设置跳转点
int longjmp(jmp_buf env, int val);
val是setjmp的返回值。
setjmp和longjmp实现了函数之间的跳转。
#include <stdio.h>
jmp_buf env;
int div2num(int a, int b);
int main(int argc, char *argv)
{
int num1, num2;
if(argc < 3)
exit(1);
num1 = atoi(argv[1]);
num2 = atoi(argv[2]);
if(setjmp(env) == 0)
printf("%d / %d = %d\n", num1, num2, div2num(num1, num2));
else
{
printf("除数不能为0\n");
scanf("%d\n", num2);
printf("%d / %d = %d\n", num1, num2, div2num(num1, num2));
}
exit(0);
}
int div2num(int a, int b)
{
if(b == 0)
longjmp(env, 1);
return a / b;
}