实验目的
1、理解
fork
系统调用工作原理,使用fork
创建子进程
2、理解execve
系统调用工作原理,使用execve
加载执行新程
3、调试跟踪fork
和execve
系统调用函数的执行过程实验内容
实验要求
主程序在创建子进程后要等待子程序执行结束才打印PID号,最后结束运
行。
程序准备
由实验内容知道,需要写三个程序,分别是lab3、leap、info。新建三个源文件。
#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的用于输出学生信息,根据情况自行修改。
#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用于判断平闰年。
#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是主程序,知识点主要包含这几个函数:fork、execve、wait、waitpid。
介绍这四个函数
参数 | 描述 |
---|---|
返回值(pid_t) | 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1 |
参数 | 描述 |
---|---|
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);
}
参数 | 描述 |
---|---|
status | 如果status不是一个空指针,则终止进程的终止状态将存储在该指针所指向的内存单元中,如果不关心终止状态,可以将 status参数设置为NULL |
返回值(pid_t) | 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中 |
参数 | 描述 |
---|---|
pid | pid<-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中的文件拷贝到当前目录
-
分别编译,加执行权限