操作系统实验:软中断+消息队列

简介: Linux进程通信,软中断+消息队列,实现了简单的聊天功能。

不知道这一年是我感觉过的快,还是大家都觉得过的快。

转眼2018年就要过去了,很长一段时间(大概三四个月)没有写博客了,随着学的东西越来越多,也越来越觉得自己是那么的无知。也就不知道该怎么下笔才好,昨天晚上肝完了操作系统实验作业,准备也写一篇博客。

现在,要开始准备明年的春招了,博客也会开始慢慢更新。

操作系统实验报告

一、 实验名称:Linux进程通信

二、 实验目的:掌握Linux进程通信的各种方式

三、 实验内容:软中断+消息队列

四、 程序清单

客户端:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include<sys/shm.h>

#include<signal.h>

#define MSG_SIZE 128
int wait_mark;

int waiting()
{
    while(wait_mark != 0);
}

void stop()
{
    wait_mark = 0;
}

struct msgbuf

{

    long mtype;

    char mtext[MSG_SIZE];

};

int main()

{
    int senderPid = -1;
    int qid;

    key_t key;

    int ret;

    struct msgbuf buf;
    /*
    函数ftok把一个已存在的路径名和一个整数标识得转换成一个key_t值,称为IPC键
    */
    key=ftok("/home/oswork", 'jzzzz');  //可以自定义,这里调用ftok函数生成消息队列的键值

    if (key<0)

    {

        perror("ftok error");

        exit(1);

    }

    qid=msgget(key, IPC_CREAT|0666);

    if (qid<0)

    {

        perror("msgget error");

        exit(1);

    }
    int flag = 1;
    while (1)

    {
        if(flag == 1)
        {
            flag = 0;
            printf("input the message:");

            fgets(buf.mtext,MSG_SIZE,stdin);

            if (strncmp(buf.mtext, "exit",4)==0)

            {

                buf.mtype=getpid();

                ret=msgsnd(qid, &buf, MSG_SIZE, 0);
                msgctl(qid, IPC_RMID,0);

                break;

            }

            buf.mtype=getpid();

            ret=msgsnd(qid, &buf, MSG_SIZE, 0);

            if (ret<0)

            {

                perror("msgsnd error");

                exit(1);

            }

            else

            {

                printf("send!\n");

            }
            wait_mark = 1;
            signal(17, stop);
            waiting();
        }
        else
        {
            flag = 1;
            memset(&buf, 0, sizeof(buf));

            if(senderPid == -1)
            {
                ret=msgrcv(qid, &buf, MSG_SIZE, 0, 0);
            }
            else
            {
                ret=msgrcv(qid, &buf, MSG_SIZE, senderPid, 0);
            }

            if(senderPid == -1)
            {
                senderPid = buf.mtype;
            }
            wait_mark = 1;

            if (ret<0)

            {

                perror("msgrcv error");

                exit(1);

            }

            else

            {

                if (strncmp(buf.mtext, "exit",4)==0)

                {
                    msgctl(qid, IPC_RMID,0);
                    break;

                }

                printf("received message:\n");

                printf("text:%s\n",buf.mtext);

                kill(senderPid, 17);
            }
        }

    }

    return 0;

}

服务端:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include<sys/shm.h>

#include<signal.h>

#define MSG_SIZE 128

int wait_mark;
int qid;

int waiting()
{
    while(wait_mark != 0);
}

void stop()
{
    wait_mark = 0;
}

void sig_handler()
{
    msgctl(qid, IPC_RMID,0);
}

struct msgbuf

{

    long mtype;

    char mtext[MSG_SIZE];

};

int main()

{
    int senderPid = -1;

    int recPid = -1;

    key_t key;

    int ret;

    struct msgbuf buf;

    key=ftok("/home/oswork", 'jzzzz');

    if (key<0)

    {

        printf("ftok error");

        exit(1);

    }

    qid=msgget(key,IPC_EXCL|0666);

    if (qid<0)

    {

        perror("msgget error");

        exit(1);

    }
    int flag = 0;

    while (1)

    {
        if(flag == 0)
        {
            flag = 1;
            memset(&buf, 0, sizeof(buf));
            if(senderPid == -1)
            {
                ret=msgrcv(qid, &buf, MSG_SIZE, 0, 0);
            }
            else
            {
                ret=msgrcv(qid, &buf, MSG_SIZE, senderPid, 0);
            }

            if(senderPid == -1)
            {
                senderPid = buf.mtype;
            }
            wait_mark = 1;

            if (ret<0)

            {

                perror("msgrcv error");

                exit(1);

            }

            else

            {

                if (strncmp(buf.mtext, "exit",4)==0)

                {

                    break;

                }

                printf("received message:\n");

                printf("text:%s\n",buf.mtext);

                kill(senderPid, 17);
            }
        }
        else
        {
            flag = 0;
            printf("input the message:");
            signal(SIGINT, sig_handler);

            fgets(buf.mtext,MSG_SIZE,stdin);

            if (strncmp(buf.mtext, "exit",4)==0)

            {
                buf.mtype=getpid();

                ret=msgsnd(qid, &buf, MSG_SIZE, 0);

                break;

            }

            buf.mtype=getpid();

            ret=msgsnd(qid, &buf, MSG_SIZE, 0);

            if (ret<0)

            {

                perror("msgsnd error");

                exit(1);

            }

            else

            {

                printf("send!\n");

            }
            wait_mark = 1;
            signal(17, stop);
            waiting();
        }

    }

    return  0;

}

五、 程序测试

此处输入图片的描述

六、 实验总结

最后,选择了“软中断+消息队列”的方式来实现了一个简单的聊天工具。
可以实现两人的在线聊天:

  1. 一人一句,不能争抢,这个机制是通过软中断信号处理来实现的,kill向指定进程发送信号,signal接受信号并进行相应的处理。
  2. 两人间对话消息的传递是通过消息队列实现的,选择消息队列而没有用管道通信是因为管道通信是按FIFO的方式单向传递的,而且只允许在建立者和子进程间使用。消息队列允许一个或多个进程向它读写消息,而且允许随机读取(按消息的类型读取,比如我程序中将消息队列标识符id就设置成了等于进程标识符pid),不是FIFO。
  3. 功能:
    a) 有两个会话A,B,

b) 一开始会话A处于等待键盘输入发送给B消息的状态,会话B处于等待接受A的发送消息的状态。
c) 键盘输入消息,A成功发送,A的状态变为等待接受B的消息,B成功接受,B的状态变为等待键盘输入文字发送给A消息。
d) 重复b,c环节
e) 直到一方输入”exit”字符串,双方同时结束会话,并且清空消息队列。

在实验中也遇到了一些问题,其中比较麻烦的是:
在我写好代码调试运行的时候,因为一方A是发送端,另一方B肯定是接受端,但一开始两边程序刚开始运行的时候,在键盘还没有输入任何字符时,接收端B会莫名其妙的“收到消息”!!!
但这个消息又不是A发送过来的,那就造成了B不能给A发送信号,告诉它“我已经收到了你的消息”,所以A还是处于等待键盘输入发送消息的状态。但此时B因为收到了消息,已经变成了等待键盘输入发送消息的状态。这样就造成了A在等B接受到消息而发送回信号,同时B也在等A接受到消息而发送回信号。但此时因为两边都是等待键盘输入准备发送消息的状态,而没有接受消息的一端,无论在A、B哪一端发消息,另一端都不会收到,僵持的状态也不会改变。
这样就造成了死锁。
重新检查了一遍代码,发现了问题出在了我没有在每次会话结束后,把消息队列清空。
于是,我在两个地方增加了清空消息队列的代码:
1. 会话正常结束,即我在程序中写的通过发送“exit”字符串的方式主动结束会话,在结束之前调用了msgctl(qid, IPC_RMID,0);来清除队列中的消息

            if (strncmp(buf.mtext, "exit",4)==0)

            {

                buf.mtype=getpid();

                ret=msgsnd(qid, &buf, MSG_SIZE, 0);
                msgctl(qid, IPC_RMID,0);

                break;

            }

2. 会话强制结束,即键盘按下Ctrl + C结束会话。通过软中断来实现。

void sig_handler()
{
    msgctl(qid, IPC_RMID,0);
}

signal(SIGINT, sig_handler);
目录
相关文章
|
4月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品体验与功能反馈摘要** 运维人员发现OS Copilot易上手,文档清晰,助其高效排查故障(8/10分)。愿意推荐并参与开源开发。亮点在于知识问答,能快速筛选答案。相较于竞品,优点是新手友好、文档清晰,但功能扩展性待增强。期望增加系统错误排查与解决方案,并集成ECS等,以优化系统安装流程。
阿里云操作系统智能助手OS Copilot实验测评报告
|
4月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
OS Copilot是针对Linux的智能助手,助力学习、运维及编程。用户界面直观,自然语言交互方便新手。官方文档详尽,但初次配置略复杂,适合学生和开发者。在提高代码编写和调试效率、系统学习上得分高,功能亮点包括代码生成、问答和命令执行。用户期待更多操作系统支持、自动错误分析和系统排查功能。
183 3
|
4月前
|
弹性计算 人工智能 运维
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云操作系统智能助手OS Copilot实验测评报告
110 2
|
4月前
|
弹性计算 运维 监控
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云OS Copilot助力学生提升学习效率,简化Linux操作。作为学生,体验者发现它在代码理解和诊断上极具价值,给予新手友好体验,但存在命令执行限制和错误处理问题。评分10/10,愿推荐并参与未来开发。功能上,知识问答、辅助编程和命令执行深受喜爱。对比其他产品,OS Copilot简洁集成,但需改善多命令支持和错误分析。期望支持更多操作系统及与ACK等工具联动,增强系统管理和故障排查。
44 1
|
4月前
|
弹性计算 运维 Linux
阿里云操作系统智能助手OS Copilot实验测评报告
体验OS Copilot对于新人使用是友好的,教程给出的比较全面,还支持语言问答,命令执行等优点,还允许用户直接在操作系统内部使用阿里云,完成ECS的实例查询等操作。但是在系统兼容上表现出不足,对于服务器地区不明确。但总体来说测评者对OS Copilot其智能化、高效化、专业化评价是高的。
|
4月前
|
弹性计算 运维
阿里云操作系统智能助手OS Copilot的实验测评报告
OS Copilot 产品体验摘要 用户角色与场景:一位计算机学生使用辅助学习和解决问题,特别是通过代码解释功能加深理解。 易用性与文档:初者可能会觉得有些细节不明确。 帮助程度:用户给予极高评价,对学习帮助大,评分10分,快速定位和解决代码问题,提升学习效率。 推荐与参与:用户愿意推荐给他人。 功能体验:用户尝试了所有功能,对知识问答、辅助编程和命令执行特别感兴趣,尤其是命令执行帮助大。 对比其他产品:OS Copilot优点是便捷、准确。 期望功能:用户希望增加自动报错分析和系统错误排查。 联动体验:用户期待,以实现更全面的工具集。 总结:整体体验积极,用户看好其潜力,期待改进和未来联动。
|
4月前
|
弹性计算 运维 Python
阿里云操作系统智能助手OS Copilot实验测评报告
**OS Copilot 产品测评摘要** - 学生使用,用于学习和编码,发现上手难度较高,指引文档不清晰,特别是Access ID设置和代码复制流程。 - 功能上,评分9分,辅助编程和知识问答功能显著提升了学习效率,减少了错误。 - 愿意推荐,并有兴趣参与开源开发以提升自我。 - 希望增强错误排查,提供具体错误原因和位置。 - 联动ACK智能助手可增强学习效果。 [链接]: https://developer.aliyun.com/topic/instructions-for-os-copilot
|
4月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot的实验测评报告
阿里云OS Copilot是AI驱动的Linux操作系统助手,助于系统管理和运维。学生反馈它在代码解释和编写上有很大帮助,给予8-9分的评价。功能亮点包括自然语言问答、辅助编程和命令解释,简化操作,提升效率。尽管易用,但需基础Linux知识。用户期待更多功能如系统优化建议和代码优化。与ACK智能助手配合,实现故障排查和运维。适合寻求效率提升的个人和团队。
70 0
|
4月前
|
弹性计算 运维 自然语言处理
阿里云操作系统智能助手OS Copilot实验测评报告
阿里云OS Copilot是面向Linux的智能助手,助运维工程师提升效率。易上手,文档清晰,对新人友好。提供自然语言问答、编程辅助,尤善理解与响应。评分10/10,推荐给同行。目前侧重辅助编程,期望支持更多OS、并发命令执行及错误分析。适合集成于ECS等,打造自动化工作流。期待开源版本与社区合作。
97 0
|
4月前
|
弹性计算 运维 安全
操作系统智能助手OS Copilot实验测评报告
**阿里云OS Copilot摘要** OS Copilot是面向开发者和学生的智能助手,尤其对学习编程和运维有显著帮助。虽然初期上手复杂,但其知识问答、辅助编程功能深受好评,评分10分。用户愿推荐给他人,并期待开源参与开发。产品优点包括多功能、便捷性和高准确度,但新手引导需改进。期望增加Windows支持和自动化错误分析功能。通过与ECS等产品联动,OS Copilot能提升整体效率,简化操作,展现云服务的未来潜力。
63 0