1.1 题目的主要研究内容及预期达到的目标
(1)编制一个程序,使其实现进程的软中断通信。 (2)父进程发信号控制子程序的终止。
1.2 题目研究的工作基础或实验条件
(1)硬件环境:linux (2)软件环境:标准C语言
1.3 设计思想
使用系统调用fork()创建两个子进程,再用系统调用signal()让父进程捕捉键盘上的中断信号(即按DEL键);当捕捉到中断信号后,父进程用系统调用Kill()向两个子进程发出信号,子进程捕捉到信号后分别输出下列信息后终止: Child Proeess 1 is Killed by Parent! Child Process 2 is Killed by Parent!
父进程等待两个子进程终止后,输出如下的信息后终止: Parent Process is Killed!
1.4 流程图如图(1)
开始 Fork函数建立两个子进程,p1,p2 显示结果,发出结束 是否成功 信号 N Y Y P1,p2进程运行 等待16,17 信号 N N 分别向p1,p2,发出16,17信等待SIGQUIT Y 号 信号
图(1):进程的软中断通信
结束 显示结果 Y 等待p1,p2结束信号 N 1.5 主要程序代码
#include void stop(),waiting(); main() { int p1,p2; if((p1=fork())==0) { flag=1; signal(16,stop);signal(2, SIG_IGN); waiting();//当flag=1时,waiting方法不进行任何操作,不停循环,直到按下^c,调 用stop()函数,使得flag=0,跳出循环; lockf(1,1,0); printf(\"\\nChild process 1 is killed by parent!\\n\"); lockf(1,0,0); exit(0);//利用exit( )来实现进程的自我终止,通常父进程在创建子进程时, //应在进程的末尾安排一条exit( ),使子进程自我终止。exit(0)表示进程正常终 止,exit(1)表//示进程运行有错,异常终止。 } else{ if((p2=fork())==0){ flag=1; signal(17,stop); signal(2, SIG_IGN); waiting(); } } lockf(1,1,0); printf(\"Child process 2 is killed by parent!\\n\"); lockf(1,0,0); exit(0); else{ } } flag=1; signal(SIGINT,stop); //*接收到^c信号,转stop* waiting(); kill(p1,16);/*向p1发软中断信号58*/ wait(0); kill(p2,17);/*向p2发软中断信号59*/ wait(0); printf(\"Parent process is killed!\\n\"); exit(0); void waiting() { } void stop() { while(flag!=0); flag=0; } 1.6 运行结果如图(2) 图(2):进程的软中断通信 1.7 心得体会 通过本次实验,掌握了如何创建进程以及进程的软中断。 题目2 进程的管道通信 2.1 题目的主要研究内容及预期达到的目标 (1)编制一段程序,实现进程的管道通信。 2.2 题目研究的工作基础或实验条件 (1)硬件环境:linux (2)软件环境:标准C语言 2.3 设计思想 编写程序实现进程的管道通信。用系统调用pipe( )建立一管道,二个子进程P1和P2分别向管道各写一句话: Child 1 is sending a message! Child 2 is sending a message! 父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,后P2)。 2.4 流程图图(1) 开始创建管道fd管道fd创建成功?是否创建子进程1是否子进程1创建成功?锁定管道写入端fd[1]将信息 “Child process 1 is sendingmessage !” 输入变量OutPipe将OutPipe里的信息写入管道写入端fd[1]解除对写入端fd[1]的锁定创建子进程2子进程2创建成功?否是锁定管道写入端fd[1]将信息 “Child process 2 is sendingmessage !” 输入变量OutPipe将OutPipe里的信息写入管道写入端fd[1]子进程1等待父进程从管道读取端fd[0]读出信息到变量InPipe解除对写入端fd[1]的锁定子进程2等待父进程从管道读取端fd[0]读出信息到变量InPipe将InPipe里的信息打印到屏幕上子进程1终止子进程2终止父进程终止结束 图(1)进程的管道通信 2.5 主要程序代码 #include /***** 但调用fork()父子进程的执行次序不确定.*/ /* 如果创建子进程失败,则退出 */ if((pid1=fork()) == -1) /* 创建子进程1 */ pid_t pid1,pid2; int fd[2]; char outpipe[50],inpipe[50]; if(pipe(fd)<0) { } /***** This is the child process 1 */ /***** fork函数被调用一次但返回两次,子进程中返回0值,而父进程中返回子进程ID; printf(\"Pipe create error!\\n\"); exit(-1); /* 创建匿名管道,fd[0]为读端,fd[1]为写端 */ { } /* 执行子进程1,向管道写入信息 */ if(pid1==0) { } else { /* 若先进入父进程,则使其等待,直到子进程1 把信息写入管道 */ /* 即:先让子进程1 把信息写入管道,后让子进程2 把信息写入管道 */ wait(NULL); /* This is the child process 2 */ /* 如果创建子进程失败,则退出 */ if((pid2=fork()) == -1) lockf(fd[1],1,0); /* 锁定管道写端,保证写入数据的完整性 */ printf(\"Error in fork().\\n\"); exit(-1); sprintf(outpipe,\"child 1 is sending a message!\"); write(fd[1],outpipe,35); /* 子进程向管道中写入信息 */ lockf(fd[1],0,0); exit(0); /* 解锁管道写端 */ /* 子进程1退出 */ { } /* 执行子进程2 */ if(pid2==0) { } else { wait(0); sleep(1); /* 若先执行父进程,则等待,直到子进程2 写入信息*/ /* 休眠1秒 */ lockf(fd[1],1,0); /* 锁定管道写端,保证写入数据的完整性 */ sprintf(outpipe,\"Child 2 is sending a message!\"); write(fd[1],outpipe,34); lockf(fd[1],0,0); exit(0); /* 解锁管道写端 */ /* 子进程2退出 */ printf(\"Error in fork().\\n\"); exit(-1); read(fd[0],inpipe,35); /* 从管道中读取信息,此信息由子进程1写入 */ printf(\"%s\\n\sleep(1); read(fd[0],inpipe,35); /* 从管道中读取信息,此信息由子进程2写入 */ /* 打印输出信息*/ } } } printf(\"%s\\n\ return 0; 2.6 运行结果如图2 图2进程的管道通信 2.7 心得体会 通过本次实验,掌握了如何创建管道以及利用管道方式进程间通信。 题目3 进程间通信设计 3.1 题目的主要研究内容及预期达到的目标 (1)消息的创建,发送和接收。 3.2 题目研究的工作基础或实验条件 (1)硬件环境:linux (2)软件环境:标准C语言 3.3 设计思想 使用系统调用msgget(),msgsnd(),msgrev()及msgctl()编制 一段消息的发送和接收程序。 3.4 流程图如图1,2 发送端图(1) 接收端图(2) 3.5 主要程序代码 #include struct msgform /*消息结构,存放消息的结构体*/ { long mtype; char mtexe[1024];/*文本长度*/ }msg; int msgqid,i; void CLIENT( ) { int i; msgqid=msgget(MSGKEY,0777); for(i=6;i>=1;i--) { msg.mtype=i; printf(\"client send message:%d\\n\ msgsnd(msgqid,&msg,1024,0);/*发送消息msg入msgid消息队列,0:当消息队列满时, //msgsnd将会阻塞,直到消息能写进消息队列*/ } exit(0); } void SERVER( ) { msgqid=msgget(MSGKEY,0777|IPC_CREAT);/*由关键字获得消息队列,0777为消息队列的存取权限, //0777|IPC_CREAT为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定消息队列的存取权限*/ do { msgrcv(msgqid,&msg,1024,0,0); /*从队列msgid接受消息msg*,msg为存放消息的结构体, // 1030为要接收消息的大小,0:为=0时接收第一个消息,>0时接收类型等于msgtyp的第一个消息, // <0时接收类型等于或者小于msgtyp绝对值的第一个消息,0: 阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待*/ printf(\"server get message:%d\\n\ }while(msg.mtype!=1); msgctl(msgqid, IPC_RMID,0); /*消息类型为1时,释放队列,msgctl获取和设置消息队列的属性,msgqid为消息队列标识符*/ exit(0); } main() { if(fork()) SERVER(); else CLIENT( ); wait(0); wait(0); } 3.6 运行结果如图3 图3: 进程间通信设计截图 3.7 心得体会 通过本次实验,掌握了如何创建消息队列进行进程间通信。 题目4 利用多线程模拟实现生产者/消费者问题。 4.1 题目的主要研究内容及预期达到的目标 (1)通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制。 4.2 题目研究的工作基础或实验条件 (1)硬件环境:linux (2)软件环境:标准C 4.3 设计思想 (1)定义缓冲池大小SIZE,创建互斥信号量mutex初始化1,控制信号量full,empty初始化0,SIZE。 (2)调用pthread_create创建1个生产者producter_tid,和1个消费者consumer_tid。 (3)生产者开始生产时,等待empty信号。等待mutex信号加锁,生产者生产,发送mutex信号解锁,发送full信号。休息随机秒后该生产者可以继续生产。 (4)消费者开始消费时,等待full信号,等待mutex信号加锁,消费者消费,发送mutex信号解锁,发送empty信号。休息随机秒后该消费者可以继续消费。 4.4 流程图 生产者图(1) 消费者图(2) 图(1) 图(2) 4.5 主要程序代码 #include #define SIZE 15 static sem_t mutex; //互斥变量 static sem_t full,empty; //有互斥变量,无互斥变量 struct product{ char products[SIZE];// 物品池 int first,end; int num; }; struct product *p; void *producter() { char c; while(1){ sem_wait(&empty); ,//它的作用是从信号量的值减去一个“1” sem_wait(&mutex); c='a'+rand() % 26; p->products[p->end]=c; p->end=(p->end+1)%SIZE ; p->num=p->num+1; printf(\"proceducer生产了%c.........产品总数为%d\\n\ sem_post(&mutex);//给信号量的值加上一个“1” sem_post(&full); sleep(rand()%3); } } void *consumer() { char c; while(1){ sem_wait(&full); //查看互斥变量,之后变量减一 sem_wait(&mutex); c=p->products[p->first]; p->first=(p->first+1)%15; p->num=p->num-1; printf(\"consumer消费了%c.........产品还剩%d\\n\ sem_post(&mutex);//互斥变量加一 sem_post(&empty); sleep(rand()%3); } } int main() { p = (struct product *) malloc(sizeof(struct product));;//全局变量p开辟堆空间 product型内存 p->first=0;p->end=0;p->num=0;//初始化 product pthread_t producter_tid,consumer_tid; sem_init(&mutex, 0, 1); //初始化互斥变量,设置互斥条件0,初值1 sem_init(&full, 0, 0); sem_init(&empty, 0, SIZE); pthread_create(&producter_tid, NULL, producter,NULL);//建立线程,绑定函数 pthread_create(&consumer_tid, NULL, consumer,NULL); pthread_join(producter_tid, NULL); pthread_join(consumer_tid, NULL);//等待进程结束 return 0; } 4.6 运行结果如图3 图3:生产者/消费者问题程序截图 4.7 心得体会 通过本次实验,对生产者消费者算法加深了理解,学会了在linux下模拟实现算法的编程方式,熟悉了linux下的C语言编程方式。 总结 通过本次操作系统课程设计,掌握了Linux平台下的相关进程通信的知识。 懂得了如何运用信号量实现进程间的互斥。对于一些概念如进程、线程、多线程、并发,消息队列,管道通讯、队列消息传递、信号量的传递等有了更深入的理解。同时在实际操作中,我对于linux运行平台的一些操作更加熟悉,对于vi编辑器等工具的使用也渐渐熟练感受到了linux命令的强大,但是也感受到了linux编程与windows编程的差距。 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务