杭电操作系统实验三报告

写给看这篇博客的杭电学弟:
按理说操作系统实验应该自己做,这样能锻炼自己。鉴于我的报告还是比较有参考价值,能让以后的同学参考一下,就做成md的形式。

在这里插入图片描述

实验三报告

一、实验内容:

(1)实验名:Linux进程管理
(2)实验要求:
1)实现一个模拟的shell
2)实现一个管道通信程序
3)利用Linux消息队列通信机制实现两个线程间的通信
4)利用Linux共享内存通信机制实现两个进程间的通信

二、实验思路

(1)实验一

pid = fork()会返回多个值,只需在fork()后使用多个判断语句即可。
pid<0表示错误,我打印error之后退出
pid=0表示子进程运行,使用execl替换进程,替换为我们想要的进程,如cmd.o。
pid>0表示父进程运行,使用wait(NULL)函数等待所有子进程的退出。

效果见实验结果(1)
代码见附录demo1

(2)实验二

使用7个信号量:
Mutex = sem_open(“Mutex”, O_CREAT, 0666, 1);
send1 = sem_open(“send1”, O_CREAT, 0666, 1);
send2 = sem_open(“send2”, O_CREAT, 0666, 1);
send3 = sem_open(“send3”, O_CREAT, 0666, 1);
receive1 = sem_open(“receive1”, O_CREAT, 0666, 0);
receive2 = sem_open(“receive2”, O_CREAT, 0666, 0);
receive3 = sem_open(“receive3”, O_CREAT, 0666, 0);

1)
建立无名管道:
int fd[2];
int ret = pipe(fd);//无名管道

2)先fork三个子进程,编写各自的操作

每个子进程等待各自的send信号量,再等待Mutex信号量,进行,完成后释放各自的receiver:
P(send)
P(Mutex)
。。。发送内容到管道。。。
V(receiver)
V(Mutex)

父进程等待三个receiver信号量,接收管道内容后,释放三个send信号量:
P(receiver1)
P(receiver2)
P(receiver3)
P(Mutex)
。。。发送内容到管道。。。
V(receiver1)
V(receiver2)
V(receiver3)
V(Mutex)

效果见实验结果(2)
代码见附录demo2

(3)实验三

四个信号量:
sem_send = sem_open(“send”, O_CREAT, 0666, 1);
sem_receive = sem_open(“receive”, O_CREAT, 0666, 0);
sem_over1 = sem_open(“over1”, O_CREAT, 0666, 0);
sem_over2 = sem_open(“over2”, O_CREAT, 0666, 0);

发送:(以sender1为例)
While(1)
{
P(send)
发送消息给接收消息队列
if(发送的是”exit”)
Break;
P(receive)
}
P(over1)
发送退出消息
V(send)
退出
接收:
Int flag1 = 0;
Int flag2 = 0;
While(1)
{
P(receive)
发送消息给接收消息队列
if(接收到的是1发来的”exit”)
Flag1 = 1
V(over1)
if(接收到的是2发来的”exit”)
Falg2 = 1
V(over2)
P(send)

If(flag1 && flag2)
Break;
}
退出

代码见附录demo3

(4)实验四

1)
共享内存中放的是字符串
支持不断地发送,不断地接收(加接收延时即可)
在发送消息中,第一位表示是哪个发送者发送的,以此区分发送者。

2)
sem_send = sem_open(“send”, O_CREAT, 0666, 2);
sem_receive = sem_open(“receive”, O_CREAT, 0666, 0);
sem_over1 = sem_open(“over1”, O_CREAT, 0666, 0);
sem_over2 = sem_open(“over2”, O_CREAT, 0666, 0);

发送:
While(1)
P(send)
发送信息
V(receive)
P(over1)
显示传回信息
V(send)

接收:
Int flag1 = 0;
Int flag2 = 0;
While(1)
P(receive)
If(是sender1发送的)
If(发送的是“exit”)
Flag1 = 1
V(over1)
If(是sender2发送的)
If(发送的是“exit”)
Falg2 = 1
V(over2)

三、实验结果与遇到的问题

(1)实验一

遇到的问题及解决:一开始父进程没有等待子进程结束导致出错

(2)实验二
经测试,可以做到不同顺序!.

遇到的问题及解决:一开始连续三个fork(),其实创建了孙子进程,并不是三个并列的子进程,正确写法是:
pid1 = fork();
if(pid1 > 0)
{
pid2 = fork();
if(pid2 > 0)
{
pid3 = fork();
}
}
遇到的问题及解决:接收的数据乱码。原因是当初放数据时,没有考虑‘\0’的存在,应该合理设计,只在最后加‘\0’。

(3)实验三

支持多终端发送,单终端接收。
发送顺序不是固定。

遇到的问题及解决:无法申请到消息队列,试过各种方法,都是返回-1。重启就行了,估计是调试太多次,把能用的消息队列都搞没了。

(4)实验四

支持多终端发送,单终端接收。
发送顺序不是固定。
四、实验总结
这个实验我是最早验收成功的。一开始,投机求巧,只完成第四个小实验的多终端,而第三个小实验依旧使用单终端多线程(参考网上的),刚好贾老师出差就找赵伟华老师验收,是想让自己碰碰运气,结果运气不好只演示第三个,结果分数有点低。一开始的心态的确和大多数人一样,觉得水水过就好了,后来看到室友都实现了第三个实验的多终端,我也不甘示弱,还是把第三个小实验重写了一下。

六、附录

1)Demo1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
   
    char input[20];
    pid_t pid;

//    printf("输入要运行的程序名$\n");
//    scanf("%s", input);
    while(1)
    {
   
        printf("输入要运行的程序名$\n");
        scanf("%s", input);

        if(strcmp(input,"exit") == 0)
        {
   
            printf("父进程退出\n");
            printf("\n进程结束,pid:%d\n", getpid());
            exit(0);
        }
        else if(strcmp(input,"cmd3") == 0 || strcmp(input,"cmd2") == 0 || strcmp(input,"cmd1") == 0)
        {
   
            //创建子进程
            pid = fork();

            if(pid < 0)
            {
   
                printf("vfork() error\n");
                exit(-1);
            }
            else if(pid == 0)
            {
   
                printf("i am the child process, my process id is %d\n",getpid());
                char path[80] = "../t1/";
                char *lastName = ".o";
                strcat(path, input);
                strcat(path, lastName);

                execl(path,"",NULL);
            }
            else
            {
   
                printf("i am the parent process, my process id is %d\n",getpid());

                pid_t temp = wait(NULL);
                printf("\n进程结束,pid:%d\n", temp);
            }
        }
        else
        {
   
            printf("Command not found\n");
//            printf("输入要运行的程序名$\n");
//            scanf("%s", input);
            continue;
        }

    }

    return 0;
}

(2)Demo2

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <stdlib.h>
#include <semaphore.h>//信号量头文件
#include <signal.h>

#define MAX_PIPE_CAPACIPY 100


int main()
{
   
    int fd[2];
    sem_t *Mutex;
    sem_t *send1, *send2, *send3;
    sem_t *receive1, *receive2, *receive3;

    sem_unlink("Mutex");
    sem_unlink("send1");
    sem_unlink("send2");
    sem_unlink("send3");
    sem_unlink("receive1");
    sem_unlink("receive2");
    sem_unlink("receive3");

    Mutex = sem_open("Mutex", O_CREAT, 0666, 1);
    send1 = sem_open("send1", O_CREAT, 0666, 1);
    send2 = sem_open("send2", O_CREAT, 0666, 1);
    send3 = sem_open("send3", O_CREAT, 0666, 1);
    receive1 = sem_open("receive1", O_CREAT, 0666, 0);
    receive2 = sem_open("receive2", O_CREAT, 0666, 0);
    receive3 = sem_open("receive3", O_CREAT, 0666, 0);

    int ret = pipe(fd);//无名管道
    if
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值