目录
一、进程环境
1、进程终止的方式
1. main返回
2. exit
3. _exit/_Exit
4. 最后一个线程从启动例程返回
5. 最后一个线程调用线程终止函数(pthread_exit(3))
6. 调用abort(3)
7. 接收到一个信号并终止
8. 最后一个线程对取消请求做出响应
2、环境表
全局变量environ是一个二级指针,包含了指向环境表的地址,遍历environ可获得进程环境表,想要使用时,可在代码中如下声明:
#include <stdio.h>
extern char **environ;
int main(void){
int i;
for (i = 0; environ[i] != NULL; i++)
printf("%s\n",environ[i]);
return 0;
}
3、C的存储空间布局
栈 |
堆 |
未初始化的数据段 |
初始化的数据段 |
正文 |
4、跳转函数
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
这是一对函数,具体的用法参照 C语言:setjmp和longjmp函数使用详解
5、进程资源限制
ulimit -a 具体用用法参照 ulimit -a详解
二、进程控制
1、进程概念
进程是系统资源分配的最小单位,运行起来的程序就是一个进程
2、进程标识
ps axj --->显示进程关系
ps aux --->进程基本状态
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);
pid_t--->非负整型数;
getpid() 返回当前进程进程ID getppid() 返回当前进程的父进程进程ID
3、进程创建
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
vfork 会阻塞父进程终止,会和父进程共享数据段
当前进程创建一个子进程,返回子进程的进程ID
子进程继承父进程的数据:
1. 用户id 组id
2. 进程表项
3. 缓存区
4. 文件屏蔽字umask
5. 环境表
6. 终端
7. 工作目录
新进程(子进程)与父进程有什么不同
1. pid
2. ppid
3. fork返回值
4. 未决信号
5. 时钟
4、fork应用场景
1. 网络服务。创建子进程,子进程跟父进程运行不一样的代码
2. shell。创建子进程,子进程被新的进程替换(exec(3))
5、终止
exit(3) 终止进程之前会调用终止处理程序,调用io缓存区清理程序
_exit(2) 直接终止
6、收尸
#include <sys/wait.h>
pid_t wait(int *stat_loc);
为任意一个子进程收尸
7、进程替换
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
具体用法可参照进程(四)exec函数、
三、练习
1、使用fork和wait
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int n = 100;
printf("hello world");
// create
pid = fork();
if (-1 == pid) {
perror("fork()");
exit(EXIT_FAILURE); // 1
}
// 两进程同时执行
if (0 == pid) {
// child
sleep(1);
printf("child pid:%d, ppid:%d\n", getpid(), getppid());
printf("child n:%d\n", n);
n++;
printf("child ++ n:%d\n", n);
_exit(0);
}
// 进程收尸
wait(NULL);
// parent
printf("parent pid:%d, ppid:%d\n", getpid(), getppid());
printf("parent n:%d\n", n);
return 0;
}
2、使用exec一族函数
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
char *arr[3] = {"ls", "-l", NULL};
pid = fork();
if (-1 == pid) {
perror("fork()");
exit(1);
}
if (0 == pid) {
// child
// execl("/bin/ls", "ls", "-l", NULL);
// execlp("test", "./text", NULL);
// execl("./test", "./test", NULL);
execv("/bin/ls", arr);
perror("execl()");
exit(1);
}
while (1) {
write(1, "*", 1);
sleep(1);
}
exit(0);
}