MacOS环境-手写操作系统-40-进程消息通讯 和 回车键处理

简介: MacOS环境-手写操作系统-40-进程消息通讯 和 回车键处理

进程消息通讯和回车键处理

1.简介

我们顺利的完成了进程间的相互切换 但当前存有的一个问题是


如果我们把输入焦点转移到命令行控制台 然后在通过Tab键 把输入焦点切换回文本框


此时存在一个问题是 命令行控制台的输入指针居然还存在


这就涉及到了进程间的通讯 一个进程将信号发送给另一个进程


让对方及时采取某些动作


由于我们在设计时 为每个进程准备了一个接收信息的队列 因此进程间相互发送消息是


可以把消息放入到接收方的队列中 当接收方从队列中获取数据时 就能收到其他进程发送过来的信息


进而及时处理


2.代码

我们先定义两个消息


一个消息对应进程终止


一个消息对应进程恢复


这两个消息定义在multi_task.h中


代码如下


#define  PROC_RESUME   0x57
#define  PROC_PAUSE    0x58
void send_message(struct TASK *sender, struct TASK *receiver, int msg);


上面代码还定义了进程间发送消息的函数send_message


第一个输入参数是发送消息的进程对象


第二个参数是接收消息的进程对象


第三个参数是要发送的消息


在主进程中 当接收到Tab键时


如果是输入焦点是切换到控制台进程 那么主进程就通过send_message给对方进程


发送一个PROC_RESUME消息 告诉对方获得了执行权限


如果输入焦点是从控制台进程切换回主进程


那么主进程就给对方发送PROC_PAUSE消息 让对方赶紧为挂起做准备


代码如下


write_vga_desktop.c

void CMain(void) {
....
    for(;;) {
    ....
        if (fifo8_status(&keyinfo) + fifo8_status(&mouseinfo) +
           fifo8_status(&timerinfo) == 0) {
            ....
            else if (data == 0x0f) {
               int msg = -1;

               if (key_to == 0) {
                   key_to = 1;
                   make_wtitle8(shtctl, shtMsgBox,"task_a", 0);
                   make_wtitle8(shtctl, sht_cons, "console", 1);
                   set_cursor(shtctl, shtMsgBox, cursor_x, COL8_FFFFFF);  
                   msg = PROC_RESUME;
               } else {
                   key_to = 0;
                   make_wtitle8(shtctl, shtMsgBox,  "task_a",1);
                   make_wtitle8(shtctl, sht_cons, "console", 0);
                   fifo8_put(&task_cons->fifo, 0x58);
                   msg = PROC_PAUSE;
               }              

              sheet_refresh(shtctl, shtMsgBox, 0, 0, shtMsgBox->bxsize, 21);
              sheet_refresh(shtctl, sht_cons, 0, 0, sht_cons->bxsize, 21);
              send_message(task_a, task_cons, msg);
           }
            ....
        }
    ....
    }
....
}

我们再看看send_message的实现


它的逻辑其实很简单 它首先把消息放入到接收进程的数据队列中 一旦进程的数据队列有数据输入时


对应的进程就会被唤起 然后发送进程把自己挂起 将CPU权限转移给接收进程


代码如下


multi_task.c
void send_message(struct TASK *sender, struct TASK *receiver, int msg) {
    fifo8_put(&receiver->fifo, msg);
    task_sleep(sender);
    }



一旦进程接收到消息后 它会在它的主循环中把消息取出 根据不同消息采取不同操作 例如对应控制台进程


如果接收到挂起消息 那么它应该把光标从窗口上抹掉 然后把控制器重新交还给主进程


如果接收到的是进程恢复消息 那么它可以重新绘制光标 并启动光标计时器 进而实现光标的重新闪动


代码如下


write_vga_desktop.c

void console_task(struct SHEET *sheet) {
....
    for(;;) {
    ....
        else {
            io_sti();
            i = fifo8_get(&task->fifo);
            if (i <= 1 && cursor_c >= 0) {
                if (i != 0) {
                    timer_init(timer, &task->fifo, 0);
                    cursor_c = COL8_FFFFFF;
                } else {
                    timer_init(timer, &task->fifo, 1);
                    cursor_c = COL8_000000;
                }

                timer_settime(timer, 50);
            }  
            else if (i == PROC_RESUME) {
                cursor_c = COL8_FFFFFF;
                timer_init(timer, &task->fifo, 0);
                timer_settime(timer, 50);
            }
            else if (i == PROC_PAUSE) {
                set_cursor(shtctl, sheet, cursor_x, COL8_000000);
                cursor_c = -1;
                task_run(task_main, -1, 0);
            }
            else if (i == 0x0e && cursor_x > 8) {
                    set_cursor(shtctl, sheet, cursor_x,COL8_000000);
                    cursor_x -= 8;
                    set_cursor(shtctl, sheet, cursor_x, COL8_000000); 
                } 
            else {
                       char c = transferScanCode(i);
                       if (cursor_x < 240 && c!=0 ) {
                           set_cursor(shtctl, sheet, cursor_x, COL8_000000);
                           char s[2] = {c, 0};
                           showString(shtctl, sheet, cursor_x, 28, COL8_FFFFFF, s);
                           cursor_x += 8;
                       }
                }

            if (cursor_c >= 0) {
                 set_cursor(shtctl, sheet, cursor_x, cursor_c);
            } 
    ....
    }
....
}

上面的部分是 进程间消息通讯

下面的部分是 回车键的处理

系统能够响应回车键的话 我们就可以实现从控制台启动应用程序

主要实现都在write_vga_desktop.c

#define KEY_RETURN  0x1C

void console_task(struct SHEET *sheet) {

    struct TIMER *timer;
    struct TASK *task = task_now();
    int i, fifobuf[128], cursor_x = 16, cursor_c = COL8_000000;
    int cursor_y = 28;

    ....

    for(;;) {
        ....
        else if (i == KEY_RETURN) {

                if (cursor_y < 28 + 112) {
                    set_cursor(shtctl, sheet, cursor_x, cursor_y, COL8_000000);
                    cursor_y += 16;
                    cursor_x = 16;
                    showString(shtctl, sheet, 8, cursor_y, COL8_FFFFFF, ">");
                }
            }
            else if (i == 0x0e && cursor_x > 8) {
                    set_cursor(shtctl, sheet, cursor_x, cursor_y, COL8_000000);
                    cursor_x -= 8;
                    set_cursor(shtctl, sheet, cursor_x, cursor_y, COL8_000000); 
                } 
            else {
                       char c = transferScanCode(i);
                       if (cursor_x < 240 && c!=0 ) {
                           set_cursor(shtctl, sheet, cursor_x, cursor_y,COL8_000000);
                           char s[2] = {c, 0};
                           showString(shtctl, sheet, cursor_x, cursor_y, COL8_FFFFFF, s);
                           cursor_x += 8;
                       }
                }

            if (cursor_c >= 0) {
                 set_cursor(shtctl, sheet, cursor_x, cursor_y, cursor_c);
            } 
      ....
    }

}


void  set_cursor(struct SHTCTL *shtctl, struct SHEET *sheet, int cursor_x, int cursor_y ,int cursor_c) {
    boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x,
               cursor_y, cursor_x + 7, cursor_y + 15);
    sheet_refresh(shtctl, sheet, cursor_x, cursor_y, cursor_x+8, cursor_y + 46);
}

我们对代码做的改动有 先定义回车键扫描码的数值0x1C 当回车键按下后


主进程会把扫描码发送给控制台进程的主函数 在控制台进程主函数中 一旦接受到回车键消息时


把cursor_y的值加上16 也就是一个字符的高度 cursor_y将作为新的显示纵坐标


我们原来显示字符时 纵坐标都是写死的 为28


现在我们把纵坐标改为可变动的情况 一旦受到回车键 系统便知道需要在新的一行显示信息


于是我们让控制台进程在窗口中另起一行 也就是将输入坐标向下移动16个字符的距离


然后无论是字符还是光标


他们的显示都在新坐标下进行


set_cursor用来绘制光标 原先光标的纵坐标是定死为28的 现在我们把纵坐标当做一个参数来处理


每次窗口想要绘制光标时 需要把光标所在的纵坐标传入


有了上面代码后 我们每次在命令行窗口中点击回车键时


命令行窗口会新起一行 字符和光标都会在新一行中显示


3.编译运行

目录
相关文章
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
70 1
|
1月前
|
调度 开发者 Python
深入浅出操作系统:进程与线程的奥秘
在数字世界的底层,操作系统扮演着不可或缺的角色。它如同一位高效的管家,协调和控制着计算机硬件与软件资源。本文将拨开迷雾,深入探索操作系统中两个核心概念——进程与线程。我们将从它们的诞生谈起,逐步剖析它们的本质、区别以及如何影响我们日常使用的应用程序性能。通过简单的比喻,我们将理解这些看似抽象的概念,并学会如何在编程实践中高效利用进程与线程。准备好跟随我一起,揭开操作系统的神秘面纱,让我们的代码运行得更加流畅吧!
|
1天前
|
监控 搜索推荐 开发工具
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
|
1月前
|
C语言 开发者 内存技术
探索操作系统核心:从进程管理到内存分配
本文将深入探讨操作系统的两大核心功能——进程管理和内存分配。通过直观的代码示例,我们将了解如何在操作系统中实现这些基本功能,以及它们如何影响系统性能和稳定性。文章旨在为读者提供一个清晰的操作系统内部工作机制视角,同时强调理解和掌握这些概念对于任何软件开发人员的重要性。
|
1月前
|
Linux 调度 C语言
深入理解操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅,从进程管理的基本概念出发,逐步探索到内存管理的高级技巧。我们将通过实际代码示例,揭示操作系统如何高效地调度和优化资源,确保系统稳定运行。无论你是初学者还是有一定基础的开发者,这篇文章都将为你打开一扇了解操作系统深层工作原理的大门。
|
1月前
|
存储 算法 调度
深入理解操作系统:进程调度的奥秘
在数字世界的心脏跳动着的是操作系统,它如同一个无形的指挥官,协调着每一个程序和进程。本文将揭开操作系统中进程调度的神秘面纱,带你领略时间片轮转、优先级调度等策略背后的智慧。从理论到实践,我们将一起探索如何通过代码示例来模拟简单的进程调度,从而更深刻地理解这一核心机制。准备好跟随我的步伐,一起走进操作系统的世界吧!
|
1月前
|
算法 调度 开发者
深入理解操作系统:进程与线程的管理
在数字世界的复杂编织中,操作系统如同一位精明的指挥家,协调着每一个音符的奏响。本篇文章将带领读者穿越操作系统的幕后,探索进程与线程管理的奥秘。从进程的诞生到线程的舞蹈,我们将一起见证这场微观世界的华丽变奏。通过深入浅出的解释和生动的比喻,本文旨在揭示操作系统如何高效地处理多任务,确保系统的稳定性和效率。让我们一起跟随代码的步伐,走进操作系统的内心世界。
|
1月前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
2月前
|
算法 Linux 调度
深入浅出操作系统的进程管理
本文通过浅显易懂的语言,向读者介绍了操作系统中一个核心概念——进程管理。我们将从进程的定义出发,逐步深入到进程的创建、调度、同步以及终止等关键环节,并穿插代码示例来直观展示进程管理的实现。文章旨在帮助初学者构建起对操作系统进程管理机制的初步认识,同时为有一定基础的读者提供温故知新的契机。
|
1月前
|
消息中间件 算法 调度
深入理解操作系统之进程管理
本文旨在通过深入浅出的方式,带领读者探索操作系统中的核心概念——进程管理。我们将从进程的定义和重要性出发,逐步解析进程状态、进程调度、以及进程同步与通信等关键知识点。文章将结合具体代码示例,帮助读者构建起对进程管理机制的全面认识,并在实践中加深理解。