SylixOS 中 CTRL + C 的大致处理流程
Q:SylixOS 中 CTRL + C 的大致处理流程
(1)当键盘按下 CTRL+C 时,主机就向目标板发送一个控制字符,其 ASSIC 码为 0x03,在 SylixOS 下常用的控制字符如下,此定义是在 tyLib.c 文件中。 - /*********************************************************************************************************
- 全局变量(控制字 __LINUX_BACKSPACE_CHAR 直接按 backspace 处理)
- *********************************************************************************************************/
- #define __LINUX_BACKSPACE_CHAR 127 /* linux 下的退格 control-? */
- #define __TTY_BACKSPACE(ptyDev, ch) ((ch) == __LINUX_BACKSPACE_CHAR || (ch) == __TTY_CC(ptyDev, VERASE))
- static CHAR _G_cTyBackspaceChar = 0x08; /* 默认值 control-H */
- static CHAR _G_cTyDeleteLineChar = 0x15; /* 默认值 control-U */
- static CHAR _G_cTyEofChar = 0x04; /* 默认值 control-D */
- static CHAR _G_cTyAbortChar = 0x03; /* 默认值 control-C */
- static CHAR _G_cTyMonTrapChar = 0x18; /* 默认值 control-X */
(2)开发板收到数据时,就转入 uart 中断处理函数中执行,中断处理函数如下:
- /*********************************************************************************************************
- ** 函数名称: imx6SioIsr
- ** 功能描述: SIO 通道中断处理函数
- ** 输 入 : psiochanChan SIO 通道
- ** 输 出 : NONE
- ** 全局变量:
- ** 调用模块:
- *********************************************************************************************************/
- static irqreturn_t imx6SioIsr (SIO_CHAN *psiochanChan, ULONG ulVector)
- {
- __PSIO_CHANNEL psiochanUart = (__PSIO_CHANNEL)psiochanChan;
- CHAR cChar;
- if (imx6UartIsTxInt(psiochanUart->iChannelNum)) { /* 发送中断 */
- while (!imx6UartTxFifoFull(psiochanUart->iChannelNum)) {
- if (psiochanUart->pcbGetTxChar(psiochanUart->pvGetTxArg, &cChar) != ERROR_NONE) {
- imx6UartTxIntDisable(psiochanUart->iChannelNum); /* 关闭发送中断 */
- break;
- } else {
- imx6UartTxFifoPut(psiochanUart->iChannelNum, cChar); /* 发送数据 */
- }
- }
- }
- while (!imx6UartRxFifoEmpty(psiochanUart->iChannelNum)) { /* 需要接收数据 */
- if (imx6UartRxFifoGet(psiochanUart->iChannelNum, &cChar) /* 接收数据 */
- == ERROR_NONE) {
- psiochanUart->pcbPutRcvChar(psiochanUart->pvPutRcvArg, cChar);
- } else {
- break;
- }
- }
- imx6UartIntClear(psiochanUart->iChannelNum); /* 清除中断 */
- return (LW_IRQ_HANDLED);
- }
由代码可知,在 uart 接受完数据后,执行了 psiochanUart->pcbPutRcvChar(psiochanUart->pvPutRcvArg, cChar) 这个函数,这个函数是注册 SIO 设备时所注册好的回调函数,其函数原型是 _TyIRd,如下所示:
- /*********************************************************************************************************
- ** 函数名称: _TyIRx
- ** 功能描述: 向终端的接收缓冲区中写入一个从硬件接收到的数据, FIFO
- ** 输 入 :
- ** ptyDev, TY 设备
- ** cInChar, 接收到的数据
- ** 输 出 : ERROR_NONE or PX_ERROR
- ** 全局变量:
- ** 调用模块:
- *********************************************************************************************************/
- INT _TyIRd (TY_DEV_ID ptyDev, CHAR cInchar)
这个函数的主要功能就是将 uart 接收到的数据上送到系统的输入缓冲区,然后进行一些处理。
(3)在 _TyIRd 中首先就对接受到的数据是否是 CTRL+C 字符做了一个判断,如下:
- if ((cInchar == __TTY_CC(ptyDev, VINTR)) &&
- (iOpt & OPT_ABORT) &&
- ((_G_pfuncTyAbortFunc != LW_NULL) ||
- (ptyDev->TYDEV_pfuncCtrlC != LW_NULL))) { /* 是否需要进行 ABORT 处理 */
- LW_SPIN_UNLOCK_QUICK(&ptyDev->TYDEV_slLock, iregInterLevel); /* 解锁 spinlock 打开中断 */
- if (ptyDev->TYDEV_pfuncCtrlC) {
- ptyDev->TYDEV_pfuncCtrlC(ptyDev->TYDEV_pvArgCtrlC);
- }
- if (_G_pfuncTyAbortFunc) {
- _G_pfuncTyAbortFunc();
- }
- }
如果是 CTRL+C 字符就执行 ptyDev->TYDEV_pfuncCtrlC(ptyDev->TYDEV_pvArgCtrlC),这个也是事先注册好的函数,其原型是 __tshellRestart,如下所示: - /*********************************************************************************************************
- ** 函数名称: __tshellRestart
- ** 功能描述: ttiny shell 线程重启 (control-C)
- ** 输 入 : ulThread 线程句柄
- ** 输 出 : NONE
- ** 全局变量:
- ** 调用模块:
- *********************************************************************************************************/
- static VOID __tshellRestart (LW_OBJECT_HANDLE ulThread)
(4)__tshellRestart 函数调用了 __tshellRestartEx 函数,__tshellRestartEx 函数将自己交给了系统的工作队列处理线程来处理,相当于将具体的 restart 操作放到了中断下半部来处理,如下所示:
- if (LW_CPU_GET_CUR_NESTING()) {
- return (_excJobAdd((VOIDFUNCPTR)__tshellRestartEx,
- (PVOID)ulThread, (PVOID)bNeedAuthen, 0, 0, 0, 0));
- }
接着会判断本线程是否存在子线程,如果存在则杀死子线程,如果不存在,则重启当前线程,如下所示: - if (ulJoin) {
- #if LW_CFG_SIGNAL_EN > 0
- kill(ulJoin, SIGKILL); /* 杀死等待的线程/进程 */
- #else
- API_ThreadDelete(&ulJoin, LW_NULL);
- #endif /* LW_CFG_SIGNAL_EN > 0 */
- iMsg = API_IoTaskStdGet(ulThread, STD_OUT);
- if (iMsg >= 0) {
- fdprintf(iMsg, "[sh]Warning: Program is killed (SIGKILL) by shell.\n"
- " Restart SylixOS is recommended!\n");
- }
- } else { /* 重启线程 */
- API_ThreadRestart(ulThread, (PVOID)__TTINY_SHELL_GET_STDFILE(ptcbShell));
- }
API_ThreadRestart 就是重启线程函数了,这里就不具体分析了。
Related Articles
如何禁止Ctrl+C执行?
Q:如何禁止Ctrl+C执行? 应用层如何控制S ylixOS 禁止 Ctrl+C 快捷键杀掉应用,参考代码如下: #include <sys/stat.h> #include <termios.h> #include <fcntl.h> static INT iOptionNoAbort, iOption; static void do_cancel_ctrlc (void) { ioctl(STD_IN, FIOGETOPTIONS, &iOption); iOptionNoAbort = ...
SHELL 中 CTRL 控制命令
SylixOS 的 shell 有几个 CTRL 命令比较特殊: CTRL + S :表示 SHELL 终端的停止操作,输入后, SHELL 不能再响应之后的输入。 CTRL + Q :表示 SHELL 终端的运行操作,输入后,可以将 SHELL 从 CTRL + S 之后返回到正常情况。 CTRL + D :表示 SHELL 终端的退出,输入后,SHELL 不能再响应输入,只能通过重启解决。
应用线程或者进程如何保证不能被Ctrl+C杀掉?
Q:应用线程或者进程如何保证不能被 Ctrl+C 杀掉? 使用 pthread_safe_np 和 pthread_unsafe_np 可以保证线程进入安全模式,避免被Ctrl+C杀掉。 更多扩展知识: 参考文章:SylixOS 中 CTRL + C 的大致处理流程 参考文章:SHELL 中 CTRL 控制命令 参考文章:如何禁止Contrl+X执行?
添加标准 C 库头文件会与 SylixOS 内部数据结构冲突
Q: 为什么加入一些标准 C 库头文件会与 SylixOS 内部数据结构冲突? SylixOS 为了提高兼容性与稳定性,SylixOS 提供了一套最适合自身多线程操作系统特点的标准 C 库(暂不包含数学库). 这套 C 库相关代码是从其他开源项目中演变而来。当然为了配合 SylixOS 系统,很多地方做出了修改。 这些库中相关的定义会随着 #include <SylixOS.h> 一同引入用户程序,当用户引用其他辅助 C 库时, 可能产生一些重复定义问题。 这里推荐使用 SylixOS 提供的 ...
SylixOS下的GIC中断实现(基于T3)
GIC常用寄存器介绍 GICD_CTLR GICv2控制器将中断分为两组。配置对应寄存器可以控制这两组中断的使能与禁能。 GICD_ISENABLERn 中断向量使能寄存器,写入1使能对应的中断向量号,写0没有影响。读取数据表示对应中断向量号的使能状态。每32个中断向量使用一个寄存器位,后续中断向量放在接下来的寄存器地址上。 GICD_ICENABLERn ...