试验六Linux进程编译.docx
《试验六Linux进程编译.docx》由会员分享,可在线阅读,更多相关《试验六Linux进程编译.docx(13页珍藏版)》请在冰豆网上搜索。
试验六Linux进程编译
《嵌入式操作系统应用开发》
课程实验报告
班级:
****************
学号:
*************
姓名:
**************
指导老师:
***************
成绩:
实验六:
Linux进程编程
一、目的与任务
目的:
了解掌握操作系统进程的特点与功能,学会借助Linux进程的功能函数进行编程。
任务:
利用C语言指令编写程序调用进程函数,完成相应功能。
二、内容、要求与安排方式
1、实验内容与要求:
1)通过简单程序编写了解掌握Linux进程编程基本概念、进程关系。
2)守护进程与多进程并发案例、守护进程的编写。
3)编程验证孤儿进程的产生与回收。
4)编程验证僵尸进程的产生与回收。
2、实验安排方式:
采用1人1组,上机在Linux系统下进行编程实验。
三、程序清单
编码头文件存放在文件”ch06.h”中:
#include#include#include"err_exit.h"#include#include#include#include#include
添加“err_exit.h”文件获取导致函数调用失败的原因;
#include#include
#defineerr_exit(MESSAGE)(\
perror(MESSAGE),\
exit
(1)\
)
(1)1-1应用程序创建进程的唯一方法是通过现有进程调用folk()函数;
注释:
用folk创建的子进程基本上是父进程的克隆,所以他包含了父进程的许多特征;
#include"ch06.h"
intglobal=5;
intmain(void)
{
pid_tpid;char*string="Iamparent";
intlocal=10;
printf("beforefork---");
if((pid=fork())<0)/*fork调用失败*/
err_exit("fork");
if(pid==0){/*子进程*/
string="Iamchild";
printf("%s,mypid=%d:
global=%d,local=%d\n",
string,getpid(),global,local);
global++;}else{/*父进程*/
printf("%s,mypid=%d:
global=%d,local=%d\n",
string,getpid(),global,local);
local++;
}
printf("Atjoinpoint,%s:
global=%d,local=%d\n",string,global,local);
exit(EXIT_SUCCESS);
}
1-2用刚建立的子进程调用exec()执行一个新程序;
#include"ch06.h"
char*env_init[]={"USER=unknow","PATH=/tmp",NULL};
char*path="/home/zkj/book/ch06/echoall";
intmain(void)
{
pid_tpid;
if((pid=vfork())<0)
err_exit("vforkerror");
elseif(pid==0){/*子进程*/
if(execle(path,"echoall","arg1","ARG2",(char*)0,env_init)<0)
err_exit("execleerror");
}
else{
if((pid=vfork())<0)
err_exit("vforkerror");
elseif(pid==0){/*子进程*/
if(execlp("./echoall","echoall","onlyonearg",(char*)0)<0)
err_exit("execleerror");
}
exit(EXIT_SUCCESS);
}
}
1-3用wait()等待子进程的返回。
用不同的信号终止进程;
#include"ch06.h"
#include"p6-3.c"//pr_exit()
intzero=0;
intmain(void)
{
pid_tpid;
intstatus;
if((pid=fork())==0)/*派生子进程1*/
exit(0);/*子进程1正常退出*/
if((pid=fork())==0)/*派生子进程2*/
abort();/*子进程2生成SIGABRT信号退出*/
if((pid=fork())==0){/*派生子进程3*/
status/=zero;/*子进程3因0作除数生成SIGFPE信号退出*/
exit(0);
}
while((pid=wait(&status))>=0)/*等待子进程*/
pr_exit(status,pid);
perror("waitover");
exit(EXIT_SUCCESS);
}
(2)守护进程;
#include
#include
#include
#include//open
#include
#include
#include
#include
#include
#defineMAXFILE65535
volatilesig_atomic_t_running=1;
intfd;
//signalhandler
voidsigterm_handler(intarg)
{
_running=0;
}
intmain()
{
pid_tpid;
char*buf="ThisisaDaemon,wcdj\n";
/*屏蔽一些有关控制终端操作的信号
*防止在守护进程没有正常运转起来时,因控制终端受到干扰退出或挂起
**/
signal(SIGINT,SIG_IGN);//终端中断
signal(SIGHUP,SIG_IGN);//连接挂断
signal(SIGQUIT,SIG_IGN);//终端退出
signal(SIGPIPE,SIG_IGN);//向无读进程的管道写数据
signal(SIGTTOU,SIG_IGN);//后台程序尝试写操作
signal(SIGTTIN,SIG_IGN);//后台程序尝试读操作
signal(SIGTERM,SIG_IGN);//终止
//test
//sleep(20);//trycmd:
./test&;kill-sSIGTERMPID
//[1]forkchildprocessandexitfatherprocess
pid=fork();
if(pid<0)
{
perror("forkerror!
");
exit
(1);
}
elseif(pid>0)
{
exit(0);
}
//[2]createanewsession
setsid();
//[3]setcurrentpath
charszPath[1024];
if(getcwd(szPath,sizeof(szPath))==NULL)
{
perror("getcwd");
exit
(1);
}
else
{
chdir(szPath);
printf("setcurrentpathsucc[%s]\n",szPath);
}
//[4]umask0
umask(0);
//[5]closeuselessfd
inti;
//for(i=0;ifor(i=3;i{
close(i);
}
//[6]settermianlsignal
signal(SIGTERM,sigterm_handler);
//openfileandsetrwlimit
if((fd=open("outfile",O_CREAT|O_WRONLY|O_APPEND,0600))<0)
{
perror("open");
exit
(1);
}
printf("\nDaemonbegintowork...,andusekill-9PIDtoterminate\n");
//dosthinloop
while(_running)
{
if(write(fd,buf,strlen(buf))!
=strlen(buf))
{
perror("write");
close(fd);
exit
(1);
}
usleep(1000*1000);//1s
}
close(fd);
//printdata
if((fd=open("outfile",O_RDONLY))<0)
{
perror("open");
exit
(1);
}
charszBuf[1024]={0};
if(read(fd,szBuf,sizeof(szBuf))==-1)
{
perror("read");
exit
(1);
}
printf("read1024bytes:
\n%s\n",szBuf);
close(fd);
return0;
}
(3)孤儿进程代码
1#include
2#include
3#include
4#include
5
6intmain()
7{
8pid_tpid;
9//创建一个进程
10pid=fork();
11//创建失败
12if(pid<0)
13{
14perror("forkerror:
");
15exit
(1);
16}
17//子进程
18if(pid==0)
19{
20printf("Iamthechildprocess.\n");
21//输出进程ID和父进程ID
22printf("pid:
%d\tppid:
%d\n",getpid(),getppid());
23printf("Iwillsleepfiveseconds.\n");
24//睡眠5s,保证父进程先退出
25sleep(5);
26printf("pid:
%d\tppid:
%d\n",getpid(),getppid());
27printf("childprocessisexited.\n");
28}
29//父进程
30else
31{
32printf("Iamfatherprocess.\n");
33//父进程睡眠1s,保证子进程输出进程id
34sleep
(1);
35printf("fatherprocessisexited.\n");
36}
37return0;
38}
(4)僵死进程代码:
#include"ch06.h"
intmain(void)
{
pid_tpid;
char*message;
intn;
printf("forkprogramstart\n");pid=fork();
switch(pid){
case-1:
exit(EXIT_FAILURE);
case0:
message="Thisischild";
n=1;
break;
default:
message="Thisisparent";
n=5;
break;
}
puts(message);
sleep(n-1);
exit(EXIT_SUCCESS);
}
四、实验过程
(1)用folk()得到子父进程的关系;
用exec()执行一个新的程序
进程的不同终止状态
(2)守护进程编写执行结果
(3)孤儿进程
(4)僵死进程执行结果;
五、实验体会
(2)守护进程:
在Linux/UNIX系统引导的时候会开启很多服务,这些服务称为守护进程(也叫Daemon进程)。
守护进程是脱离于控制终端并且在后台周期性地执行某种任务或等待处理某些事件的进程,脱离终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的中断信息所终止。
(3)孤儿进程:
一个父进程退出,而它的一个或多个子进程还在进行,那么那些子进程将成了孤儿进程,孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
指导教师评语: