内核编程篇-01-创建进程、进程终结

1、进程的由来

程序

静态文件

进程

运行着的实体

查看进程之间的关系

pstree

在这里插入图片描述

操作系统如何区分进程

PID:进程的身份证

ps -ef | more

在这里插入图片描述

q 来退出命令

2、创建一个新进程

在这里插入图片描述

fork函数

头文件:

#include <unistd.h>c

函数原型:

pid_t fork(void);

返回值:

成功 :0或其他正整数

失败:-1

fork函数特性

  • 执行fork函数之后,fork函数会返回两次

  • 在旧进程中返回时,返回值为0

  • 在新进程返回时,返回值为进程的pid

叫做复制一个进程更加贴切

fork函数要点总结

在执行fork函数之前,操作系统只有一个进程,fork函数之前的代码只会被执行一次。

在执行fork函数之后,操作系统有两个几乎一样的进程,fork函数之后的代码会被执行两次。

#include <unistd.h>
#include <stdio.h>

int main()
{ 
	pid_t i;
	printf("before fork!\r\n");
	i = fork();
	printf("after fork:i=$d\r\n",i);
	return 0;
}

执行命令:

在这里插入图片描述

3、子进程偷梁换柱

exec函数族

常用后缀:

l:代表以列表形式传参(list)
v:代表以矢量数组形式传参(vector)
p:代表使用环境变量Path来寻找指定执行文件
e:代表用户提供自定义的环境变量

头文件:

#include <unistd.h>

函数原型:

int execl(const char *path, const char *arg, ...)
    
运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
	pid_t result;
	result = fork();
	if (result > 0)
	{
		execl("/bin/ls", "ls", "-l",NULL);
		printf("error!!\r\n");
		return -1;
	}
	return 0;
}

运行结果: 
总用量 24
-rw-rw-r-- 1 xiaolei xiaolei  1936 321 10:24 execl.o
-rwxrwxr-x 1 xiaolei xiaolei 16784 321 10:24 test_execl
int execlp(const char *file, const char *arg, ...)

运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
	pid_t result;
	result = fork();
	if (result > 0)
	{
		execlp("ls", "ls", "-l",NULL);
		printf("error!!\r\n");
		return -1;
	}
	return 0;
}

运行结果:
总用量 12
drwxrwxr-x 2 xiaolei xiaolei 4096 321 10:44 build
-rw-rw-r-- 1 xiaolei xiaolei  198 321 10:43 execlp.c
-rwxrwxr-x 1 xiaolei xiaolei  677 321 10:44 makefile

int execv(const char *path, char *const argv[])

运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
	pid_t result;
	char *arg[]={"ls","-l",NULL};
	result = fork();
	if (result > 0)
	{
		execv("/bin/ls",arg);
		printf("error!!\r\n");
		return -1;
	}
	return 0;
}

运行结果:
总用量 12
drwxrwxr-x 2 xiaolei xiaolei 4096 321 10:51 build
-rw-rw-r-- 1 xiaolei xiaolei  220 321 10:51 execv.c
-rwxrwxr-x 1 xiaolei xiaolei  676 321 10:51 makefile

int execve(const char *path, char *const argv[],char *const envp[])

运行代码:
#include <unistd.h>
#include <stdio.h>
int main()
{
	pid_t result;
	char *arg[]={"env",NULL};
	char *env[]={"PATH=/tmp","name=xiaolei",NULL};
	result = fork();
	if (result > 0)
	{
		execve("/usr/bin/env",arg,env);
		printf("error!!\r\n");
		return -1;
	}
	return 0;
}

运行结果:
PATH=/tmp
name=xiaolei

返回值:

成功:不返回

失败:-1

要点总结

  • l后缀和v后缀必须两者选其一来使用

  • p后缀和e后缀是可选的,可用可不用

  • 组合后缀的相关函数还有很多,可自己进一步了解

exce函数有可能执行失败,需要预防

  • 新程序的文件路径出错
  • 传参或者是自定义环境变量时,没有加NULL
  • 新程序没有执行权限

4、进程的退出

正常退出:
  • 从main函数return
  • 调用exit()函数终止
  • 调用_exit()函数终止
exit和_exit退出函数

头文件:

#include <unistd.h>
#include <stdlib.h>

原型:

void _exit(int status);
void exit(int status);

返回值:

不返回

5、等待子进程的终结

wait函数

头文件

#include <sys/wait.h>

函数原型

pid_t wait(int *status)

返回值

  • 成功:退出的子进程的pid
  • 失败:-1
处理子进程退出状态值的宏
  • WIFEXITED(status) :如果子进程正常退出,则该宏为真
  • WEXITSTATUS(status):如果子进程正常.退出,则该宏获取子进程的退出值

6、进程的"生老病死"

进程状态:
  • TASK_RUNNING:就绪/运行状态
  • TASK_INTERRUPTIBLE:可中断睡眠状态
  • TASK_UNINTERRUPTIBLE:不可中断睡眠状态
  • TASK_TRACED:调试态
  • TASK_STOPPED:暂停状态
  • EXIT_ZOMBIE:僵死状态
  • EXIT_DEAD:死亡态

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值