linux c 进程创建 execlp

#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;
	
}


猜你喜欢

转载自blog.csdn.net/Big_Study_Father/article/details/89164669
今日推荐