Linux进程的创建(Linuxlab平台)

实验目的

1、理解 fork 系统调用工作原理,使用 fork 创建子进程
2、理解 execve 系统调用工作原理,使用 execve 加载执行新程
3、调试跟踪 forkexecve 系统调用函数的执行过程

实验内容

在这里插入图片描述在这里插入图片描述

实验要求

主程序在创建子进程后要等待子程序执行结束才打印PID号,最后结束运
行。


程序准备

由实验内容知道,需要写三个程序,分别是lab3、leap、info。新建三个源文件。
在这里插入图片描述

  • info.c
#include <stdio.h>
int main( int argc, char** argv ) {
	printf( "Class:%s\n", "software 501" );
	printf( "Student ID:%s\n", "173401050117" );
	printf( "Student name:%s\n", "Liao Jie" );
	return 0;
}

info的用于输出学生信息,根据情况自行修改。

  • leap.c
#include <stdio.h>
int main( int argc, char** argv ) {
	int year = -1;
	printf( "Please Enter Year:" );
	fflush( stdout ); //清除缓存区
	scanf( "%d", &year );
	if( year%400 == 0 || year%100!=0 && year%4==0 )
		printf( "%d is leap year\n", year );
	else
		printf( "%d is not leap year\n", year );
	return 0;
}

fflush的作用详见百科-fflush,不这样做的话,printf的内容会在scanf输入之后输出,因为在scanf输入之前,字符串被放入了缓存区内。经验来自C/C++执行scanf优先于printf。leap用于判断平闰年。

  • lab3.c
#define __LIBRARY__
#include <stdio.h>
#include <unistd.h>

int main( int argc, char** argv ) {
	int choice = -1, pid = -1;
	printf("1.student infomation\n2.Leap Year\n3.Exit\nplease enter your choice:\n");
	while( 1 ) {
		scanf("%d", &choice);
		if( choice%3 > 2 || choice <= 0 ) return -1;
		else {
			switch( choice ) {
				case 1:
					pid = fork();
					if( pid < 0 ) return -1; 	
					if( pid ) {					
						printf("NO.1 child process:PID=%d\n", pid);
						waitpid( pid, NULL, 0 );
						printf("Parent process:PID=%d\n", getpid());
					}
					else {						
						execve( "info", NULL, NULL );
					}
				break;
				case 2:
					pid = fork();
					if( pid < 0 ) return -1; 	
					if( pid ) {					
						printf("NO.2 child process:PID=%d\n", pid);
						waitpid( pid, NULL, 0 );
						printf("Parent process:PID=%d\n", getpid());
					}
					else {						
						execve( "leap", NULL, NULL );
					}
				break;
				case 3:
					return 0;
				break;
			}
		}
		printf( "please enter your choice:\n" );
	}
}

lab3是主程序,知识点主要包含这几个函数:forkexecvewaitwaitpid

介绍这四个函数

  • fork pid_t fork( void )
参数描述
返回值(pid_t)若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
  • execve int execve(const char * filename,char * const argv[ ],char * const envp[ ])
参数描述
filename文件路径
argv利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束
envp传递给执行文件的新环境变量数组
返回值(int)如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中

范例

#include<unistd.h>
main(){
	char * argv[ ]={"ls","-al","/etc/passwd",(char *)0};
	char * envp[ ]={"PATH=/bin",0};
	execve("/bin/ls",argv,envp);
}
  • wait pid_t wait (int * status)
参数描述
status如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中,如果不关心终止状态,可以将 status参数设置为NULL
返回值(pid_t)如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中
  • waitpid pid_t waitpid(pid_t pid,int * status,int options)
参数描述
pidpid<-1 等待进程组识别码为 pid 绝对值的任何子进程
pid=-1 等待任何子进程,相当于 wait()
pid=0 等待进程组识别码与目前进程相同的任何子进程
pid>0 等待任何子进程识别码为 pid 的子进程
status子进程的结束状态值会由参数 status 返回,参数 status 可以设成 NULL
options提供了一些额外的选项来控制waitpid,参数 option 可以为 0 或可以用‘|’运算符把它们连接起来使用
返回值(pid_t)与options内容有关

等待标识码为pid的进程结束可用waitpid(-1,NULL,0)


步骤

  • 创建Linux011 Kernel项目,打开FloppyImageEditor,使用它是为了将windows上的文件传输到Linux磁盘

    在这里插入图片描述

  • 打开项目目录下的软盘b

    在这里插入图片描述

  • 把写好的三个源文件添加进去,保存

    在这里插入图片描述

  • 回到linuxlab F5调试 用mcopy将源文件copy到Linux磁盘

    将软盘b中的文件拷贝到当前目录
    在这里插入图片描述

  • 分别编译,加执行权限

    在这里插入图片描述


结果

在这里插入图片描述


TIPS

  • 一键拷贝
    vi创建一个批处理文件in.sh,插入mcopy -n b:leap.c leap.cmcopy b:info.c info.cmcopy -n b:lab3.c lab3.c,然后运行in.sh可以实现一键拷贝。(-n 表示若有同名文件不用询问直接覆盖)
    在这里插入图片描述
    在这里插入图片描述
  • 一键编译
    同理,也可以实现一键编译:vi make.sh,插入gcc leap.c -o leapgcc info.c -o infogcc lab3.c -o lab3
    在这里插入图片描述
  • vi编辑源文件
    当然,直接在Bochs内写源文件是可行的,如果可以忍受他的响应时间和vi的编辑习惯的话。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值