linux操作系统课程设计报告书_操作系统课程设计报告
linux操作系统课程设计报告书由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“操作系统课程设计报告”。
题目1 进程软中断通信
1.1 题目的主要研究内容及预期达到的目标
实现进程的软中断通信:父进程发信号控制子程序的终止。
1.2 题目研究的工作基础或实验条件
(1)硬件环境:Linux平台。(2)软件环境:标准C语言。
1.3 设计思想
系统调用fork()创建两个子进程,再调用signal()让父进程捕捉键盘上的中断信号(即按Ctrl + C键);当捕捉到中断信号后,父进程调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止:
Child Proce 1 is Killed by Parent!Child Proce 2 is Killed by Parent!
父进程等待两个子进程终止后,输出如下的信息后终止:
Parent Proce is Killed!
1.4 流程图
创建子进程p1NoP1 > 0Yes创建子进程p2No子进程P2等待父进程SIGSUR2消息后输出Child Proce 2 is Killed by Parent!子进程P1等待父进程SIGSUR1消息后输出Child Proce 1 is Killed by Parent!P2 > 0Yes
父进程等待子进程都结束后输出Parent proce is killed!1.5 主要程序代码
#include“stdio.h” #include“unistd.h” #include“signal.h” #include“sys/types.h” #include“stdlib.h” int k = 0;int p1,p2;// pid_t child1 = 0,child2 = 0;void func_father(int sig)// 父进程信号处理函数; { // 传送参数sig指定的信号给参数pid指定的进程;返回值:0:成功;-1:出错; // 信号宏名:SIGUSR1,用户定义信号1,信号值:10,默认动作:终止进程;
} void func_p1(int sig)// 子进程p1信号处理函数; { k=1;// 标志相应SIGUSR1消息结束;} kill(p1, SIGUSR1);kill(p2, SIGUSR2);
void func_p2(int sig)// 子进程p2信号处理函数; { k=1;// 标志相应SIGUSR2消息结束;} int main(){
while((p1 = fork())==-1);// fork()=-1创建子进程失败;
if(p1 > 0)// 父进程继续创建子进程p2; {
}
else // 子进程p1 while((p2 = fork())==-1);if(p2 > 0)// 父进程 { // 设置信号处理方式,依照参数signum指定的信号编号设置处理函数; // 指定信号到达时跳转到参数handler指定的函数执行;
// 返回值:成功:返回先前信号处理函数指针;出错:SIG_ERR(-1);
} else {
} signal(SIGINT, SIG_IGN);// 忽略本应给父进程的按键中断; signal(SIGUSR2, func_p2);// 接收父进程的消息后转到处理函数; k = 0;while(k == 0);
// 等待子进程2收到父进程的消息后置k=1
// 子进程p2 signal(SIGINT, func_father);wait(0);// 等待子进程1结束 wait(0);// 等待子进程2结束 printf(“Parent proce is killed!n”);exit(0);
printf(“Child Proce 2 is Killed by Parent!n”);exit(0);
{
} } return 0;signal(SIGINT, SIG_IGN);// 忽略本应给父进程的按键中断; signal(SIGUSR1, func_p1);// 接收父进程的消息后转到处理函数; k = 0;while(k == 0);
// 等待子进程1收到父进程的消息后置k=1 printf(“Child Proce 1 is Killed by Parent!n”);exit(0);1.6 运行结果及分析
当按下Ctrl + C后,产生消息响应。
1.7 心得体会
通过本次实验,掌握了如何创建进程以及进程的软中断。
题目2 进程的管道通信
2.1 题目的主要研究内容及预期达到的目标
实现进程的管道通信。
2.2 题目研究的工作基础或实验条件
(1)硬件环境:Linux平台。(2)软件环境:标准C语言。
2.3 设计思想
使用系统调用pipe()建立一条管道线;两个子进程P1和P2分
别向管道各写一句话:
Meage from Child l!Meage from Child 2!
父进程从管道中读出来自于两个子进程的信息,显示在屏幕上。
要求父进程先接收子进程P1的消息,再接收子进程P2的消息。
2.4 流程图
创建管道创建子进程p1NoP1 = 0Yes“Meage from Child l!”放入缓冲区中把缓冲区所指内容写入50个字节到fd[1]指定的文件No创建子进程p2P2 = 0Yes“Meage from Child 2!”放入缓冲区中把缓冲区所指内容写入50个字节到fd[1]指定的文件父进程从管道读出长度为50字节的字符串,并打印
2.5 主要程序代码
#include #include #include int pid1,pid2;// pid_t pid1,pid2;main(){
int fd[2];// 打开文件的文件描述符数组fd[0]读,fd[1]写;
char outpipe[100],inpipe[100];
pipe(fd);// 先创建管道,再创建子进程
while((pid1 = fork())==-1);// fork()=-1创建子进程失败
if(pid1 == 0)// Child1
{ lockf(fd[1],1, 0);// 建立互斥文件锁
sprintf(outpipe,“Meage from Child l!”);// 把串放入数组outpipe中
write(fd[1], outpipe, 50);// 把outpipe所指内存写入50个字节到fd[1]的文件;
sleep(5);
/*自我阻塞5秒*/ lockf(fd[1],0,0);// 解除互斥文件锁
exit(0);
}
else // pid1 > 0
{
while((pid2 = fork())==-1);
if(pid2 == 0)// Child2
{
lockf(fd[1],1, 0);/*互斥*/
sprintf(outpipe,“Meage from Child 2!”);
write(fd[1], outpipe, 50);
sleep(5);
lockf(fd[1], 0, 0);
exit(0);
}
else // pid1 > 0 && pid2 > 0,父进程
{
wait(0);
/*同步*/
read(fd[0], inpipe, 50);
/*从管道中读长为50字节的串*/
printf(“%sn”, inpipe);
wait(0);
read(fd[0], inpipe, 50);
printf(“%sn”, inpipe);
exit(0);
}
}} 1.6 运行结果及分析
父进程先接收子进程1的消息再接受子进程2的消息,并打印。
1.7 心得体会
通过本次实验,掌握了如何创建管道以及利用管道方式进程间通信。
题目3 进程间通信设计
3.1 题目的主要研究内容及预期达到的目标
利用消息队列实现进程间的通信。
3.2 题目研究的工作基础或实验条件
(1)硬件环境:Linux平台。(2)软件环境:标准C语言。
3.3 设计思想
使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制一长度为512B的消息的发送和接收程序。
3.4 流程图 用ftok函数建立IPC通信需要的ID值发送端用ftok函数返回IPC通信需要的ID值接收端用msgget函数返回队列标识符用msgget函数创建消息队列并返回标识符向缓冲区中输入1K的字符串消息清空接收缓冲区用msgsnd函数发送消息到消息队列用msgrcv函数接收消息队列中消息
3.5 主要程序代码 发送方主要代码:
int main(int argc, char **argv)
{
int msqid;
struct msgbuf buf;
int flag;// 发送消息返回值0:成功;
int key;// 创建IPC通讯ftok出的键值;
int sendlength;// 发送消息的大小,不含消息类型long占用的4个字节;
key = ftok(“msg.tmp”, 0x01);// 返回系统建立IPC通讯时需要的ID值;
if(key
{
perror(“ftok key error”);
return-1;
}
msqid = msgget(key, 0600 | IPC_CREAT);// 创建队列对象并返回标识符;
if(msqid
{
perror(“create meage queue error”);
return-1;
}
buf.mtype = 1;
strcpy(buf.mtext, “This is a test of Inter-Progre Connumation
which made by Shi Zhongyu who majors in Computing Science
and Technology, Information Science and Engineering School,Shen Yang University of Technology.”);
sendlength = sizeof(struct msgbuf)sizeof(long);// 接收消息的大小;
memset(&buf1, 0x00, sizeof(struct msgbuf));// 清空buf1结构体;
mtype = 1;// mtype > 0 :接收类型等于发送消息类型的第一个消息;
// 从标识符msqid的队列读取消息存于msgp,再删除队列中消息;
flag = msgrcv(msqid, &buf1, recvlength ,mtype, 0);if(flag
perror(“recv meage errorn”);
return-1;} printf(“ meage :%sn”, buf1.mtext);
system(“ipcs-q”);// 创建子进程执行命令:显示消息队列;
return 0;} 3.6 运行结果及分析
先发送消息到已存在的文件msg.tmp,读取消息后自动删除消息。再利用ipcrm-q 294912(msqid)删除该消息队列。
3.7 心得体会
通过本次实验,掌握了如何创建消息队列进行进程间通信。
题目4 利用多进程实现生产者消费者问题
4.1 题目的主要研究内容及预期达到的目标
利用多进程实现生产者消费者问题。
4.2 题目研究的工作基础或实验条件
(1)硬件环境:Linux平台。(2)软件环境:标准C语言。
4.3 设计思想
创建两个子进程;一个子进程(生产者进程)依次向缓冲区写
入整数0,1,2,...,9;另一个子进程(消费者进程)暂停5s后,从缓冲区读数,每次读一个,并将读出的数字从缓冲区删除,然后将 数字显示出来;父进程等待子进程2(消费者进程)的退出信息,待收集到该信息后,父进程就返回。
4.4 流程图
创建管道创建子进程p1NoP1 = 0Yes向缓冲区递增写入0到9创建子进程p2把缓冲区所指内容写入10个字节到fd[1]指定的文件No让子进程p1与p2轮流执行,并打印运行结果P2 = 0Yes暂停5秒,等待生产者写数把fd[0]所指文件传送10个字节到缓冲区指针所指的内存中,并打印出来
3.5 主要程序代码 int main(void)
{
int i = 0;int *nCount;
int fd[2];// 打开文件描述符数组fd[0]读fd[1]写;
char szBuff[11] = {0};int status;
pipe(pfd);// 先创建管道,再创建子进程
while((pid1 = fork())==-1);// fork()=-1创建子进程失败;
if(pid1 == 0)// Child1,生产者进程
{
nCount =(int *)(malloc(sizeof(int)* 10));// 分配40个字节的内存块;
for(i = 0;i
{
nCount[i] = i;
sprintf(szBuff, “%s%d”, szBuff, nCount[i]);// 向szBuff中写入“0i”;
}
write(fd[1], szBuff, strlen(szBuff));// 把szBuff所指的内存到fd[1]的文件;
free(nCount);// 释放内存块;
close(fd[0]);close(fd[1]);
}
else // pid1 > 0
{
while((pid2 = fork())==-1);
if(pid2 == 0)// Child2,消费者进程
{
sleep(5);
read(fd[0], szBuff, 10);// 把fd[0]的文件传送到szBuff指向的内存中;
printf(“%sn”, szBuff);
close(fd[0]);close(fd[1]);
}
else // pid1 > 0 && pid2 > 0,父进程
{
pid1 = wait(&status);// wait(0);
/*同步*/
i = WEXITSTATUS(status);
printf(“child1 is %d ,exit status =%dn”, pid1, i);
pid2 = wait(&status);
i = WEXITSTATUS(status);
printf(“child2 is %d ,exit status =%dn”, pid2, i);
}
}
close(fd[0]);close(fd[1]);
return 0;
} 4.6 运行结果及分析
生产者进程依次想缓冲区写入0~9,消费者进程暂停5秒后从缓冲区读数,读一个删一个。然后将数字显示出来,并打印子进程号。
4.7 心得体会
通过本次实验,掌握了如何创建消息队列进行模拟生产者消费者问题。
总结
通过本次操作系统课程设计,掌握了Linux平台下的相关进程通信的知识。以下是自己通过查阅相关文献整理的Linux系统编程的部分学习笔记。
进程间通信类型有:管道、信号、消息队列等。
进程间通信的目的:数据传输、共享数据、通知事件、资源共享、进程控制。管道是将两个file结构指向同一临时VFS索引节点,VFS索引节点指向同一物理页的一种通信方式;适用于输入、输出数据量特别大时的父子进程间通信IPC机制;所有进程完成管道操作后,索引节点被丢弃,共享数据页被释放。通常先用pipe函数创建一个管道,再通过fork函数创建一个子进程。信号的发生由两类事件引起:硬件原因,如在终端上按DELETE键产生中断信号SIGINT;软件原因,如kill、raise、alarm、setitimer等系统函数,除0的非法运算也会引起信号发送。进程能对每个信号设置独立的处理方式:能忽略信号;也能设置其处理程序(称捕捉),或对信号不做处理,执行系统默认动作; 进程能通过信号集操作函数设置对信号的阻塞(block)标志;信号被设置为阻塞后发生时,和正常的信号一样被传送(deliver)给进程,但只有进程解除其的阻塞才会被处理。即信号被阻塞后,进程不能阻止其的发生,仅阻止其不能被处理;
从信号被传递给进程到其得到处理的时间间隔称信号挂起、未决或被搁置。SIGSTOP和SIGKILL信号不能被捕捉、忽略、阻塞,保证了系统管理员在任何时候都能暂停信号和杀死信号接收某个进程。信号分为可靠(信号值在32~63,支持排队)和不可靠信号(信号值小于32,不支持排队)。信号的操作方式有:忽略信号、捕捉信号和系统默认动作。
消息是在内核地址空间的一个内部链表,每个队列都有唯一的标识号。创建消息队列时,内核创建、存储及维护着msqid_ds结构的一个实例。消息队列函数:msgget、msgctl、msgsnd、msgrcv。