#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv){
pid_t pid;
// foke a child process
pid = fork();
/*
* fork() 是一个 用户态API 集成了系统调用 sys_fork() 创建进程
* fork执行后会展开一段包含 int 0x80的编程异常指令 触发异常,进入内核态
*
* */
/* sys_fork()
* 1.为子进程找到可用的pid(即last_pid,也是 sys_fork的返回值 )
* 2.调用copy_process 复制父进程的PCB数据到子进程PCB
* 3.复制完成 设置子进程的父进程号,将进程tss结构体中的eax寄存器的值
* 设置为0,将子进程的状态设置为就绪态,从而使得子进程后面可以得到CPU
的调度
*
* */
/*子进程创建完成后 操作系统选择
* 如果将要调度的是父进程:
* system_call将系统调用sys_fork的返回值(子进程的pid )存入寄存器
eax中,执行异常返回操作从内核返回到用户态
* 从父进程int 0x80后的下一条指令开始执行,也就是执行movl eax, res;
return res,实现父进程从fork() API调用的返回,返回值就是保存在eax
寄存器的last_pid。
*
* 如果将要调度的是子进程:
* 子进程的pcb中的寄存器保存的,是和父进程通过int 0x80编程异常进入内核
处理函数时一样的指令地址,即:子进程也是从int 0x80后面的指令
* movl eax, res; return res开始执行
* 子进程的eax的值被设置为0,从而子进程开始执行时的指令流程,和父进程从
异常处理函数system_call返回到用户空间后的执行流程是一样的,将eax的
值作为fork()API的返回值
* 完成子进程像是从fork()API返回的样子,但实质只是其执行流程是从fork()
API返回处开始执行的,且返回值是0。
*
* */
if (pid< 0){
fprintf (stderr,"Fork failed!\n");
}
else if (0==pid){
/*exec 底层都是通过execve系统调用实现
*正确执行不返回 执行错误返回-1
* *l 第一个参数需要指定 路径
* *p 从环境变量中查找并执行
*
*
* */
execlp ("pwd","-al",NULL); //printf不会执行
printf("Child process!\n");
}
else{
/* 一旦调用了wait,立即阻塞自己,并检测子进程是否结束,如果找到
则彻底销毁后返回,如果没有找到,则会一直阻塞。
* wait(NULL)只在意子进程是否结束
*
*
* */
wait(NULL);
printf("Father process\n");
}
return 0;
}
linux c 进程创建 execlp
猜你喜欢
转载自blog.csdn.net/Big_Study_Father/article/details/89164669
今日推荐
周排行