更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
console.c 文件参考

浏览源代码.

枚举

enum  { STAT_NORMAL_KEY , STAT_ESC_KEY , STAT_MULTI_KEY }
 根据VT终端标准 <ESC>[37m 为设置前景色 更多...
 

函数

STATIC UINT32 ConsoleSendTask (UINTPTR param)
 控制台发送任务 更多...
 
STATIC SPIN_LOCK_INIT (g_consoleSpin)
 初始化控制台自旋锁 更多...
 
STATIC SPIN_LOCK_INIT (g_consoleWriteSpinLock)
 
INT32 GetFilepOps (const struct file *filep, struct file **privFilep, const struct file_operations_vfs **filepOps)
 
INT32 ConsoleTcGetAttr (INT32 fd, struct termios *termios)
 获取控制台 模式值 更多...
 
INT32 ConsoleTcSetAttr (INT32 fd, INT32 actions, const struct termios *termios)
 设置控制台 模式值 更多...
 
STATIC UINT32 ConsoleRefcountGet (const CONSOLE_CB *consoleCB)
 
STATIC VOID ConsoleRefcountSet (CONSOLE_CB *consoleCB, BOOL flag)
 设置控制台引用次数,也表示占用控制台的数量 更多...
 
BOOL IsConsoleOccupied (const CONSOLE_CB *consoleCB)
 控制台是否被占用 更多...
 
STATIC INT32 ConsoleCtrlCaptureLine (CONSOLE_CB *consoleCB)
 铺捉到 ctrl + 字符, 例如 ctrl + c 更多...
 
STATIC INT32 ConsoleCtrlCaptureChar (CONSOLE_CB *consoleCB)
 铺捉到 ctrl + 右方向键(>) 更多...
 
STATIC INT32 ConsoleCtrlRightsCapture (CONSOLE_CB *consoleCB)
 
STATIC INT32 ConsoleCtrlRightsRelease (CONSOLE_CB *consoleCB)
 
STATIC CONSOLE_CBOsGetConsoleByDevice (const CHAR *deviceName)
 
STATIC INT32 OsGetConsoleID (const CHAR *deviceName)
 获取控制台ID,(/dev/console1 = SERIAL, /dev/console2 = telnet) 更多...
 
STATIC INT32 OsConsoleFullpathToID (const CHAR *fullpath)
 通过路径找到控制台ID 更多...
 
STATIC BOOL ConsoleFifoEmpty (const CONSOLE_CB *console)
 
STATIC VOID ConsoleFifoClearup (CONSOLE_CB *console)
 
STATIC VOID ConsoleFifoLenUpdate (CONSOLE_CB *console)
 控制台buf长度更新 更多...
 
STATIC INT32 ConsoleReadFifo (CHAR *buffer, CONSOLE_CB *console, size_t bufLen)
 读取 更多...
 
INT32 FilepOpen (struct file *filep, const struct file_operations_vfs *fops)
 打开串口或远程登录 更多...
 
STATIC INLINE VOID UserEndOfRead (CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops)
 向控制台buf中写入结束字符 更多...
 
STATIC INT32 UserShellCheckUDRL (const CHAR ch, INT32 *lastTokenType)
 用户shell检查上下左右键 更多...
 
STATIC INT32 IsNeedContinue (CONSOLE_CB *consoleCB, char ch, INT32 *lastTokenType)
 是否需要继续 更多...
 
STATIC VOID EchoToTerminal (CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, char ch)
 输出到终端 更多...
 
STATIC VOID StoreReadChar (CONSOLE_CB *consoleCB, char ch, INT32 readcount)
 存储读取的字符 更多...
 
VOID KillPgrp (UINT16 consoleId)
 杀死进程组 更多...
 
STATIC INT32 UserFilepRead (CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
 使用参数buffer将控制台的buf接走 更多...
 
INT32 FilepRead (struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
 从串口或远程登录中读数据 更多...
 
INT32 FilepWrite (struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen)
 写数据到串口或远程登录 更多...
 
INT32 FilepClose (struct file *filep, const struct file_operations_vfs *fops)
 关闭串口或远程登录 更多...
 
INT32 FilepIoctl (struct file *filep, const struct file_operations_vfs *fops, INT32 cmd, unsigned long arg)
 
INT32 FilepPoll (struct file *filep, const struct file_operations_vfs *fops, poll_table *fds)
 
STATIC INT32 ConsoleOpen (struct file *filep)
 对 file_operations_vfs->open 的实现函数,也就是说这是 打开控制台的实体函数. 更多...
 
STATIC INT32 ConsoleClose (struct file *filep)
 关闭控制台 更多...
 
STATIC ssize_t DoRead (CONSOLE_CB *consoleCB, CHAR *buffer, size_t bufLen, struct file *privFilep, const struct file_operations_vfs *fileOps)
 
STATIC ssize_t ConsoleRead (struct file *filep, CHAR *buffer, size_t bufLen)
 任务从控制台读数据,例如 Shell Entry 任务会从此读数据 更多...
 
STATIC ssize_t DoWrite (CirBufSendCB *cirBufSendCB, CHAR *buffer, size_t bufLen)
 
STATIC ssize_t ConsoleWrite (struct file *filep, const CHAR *buffer, size_t bufLen)
 用户任务写数据到控制台 更多...
 
STATIC INT32 ConsoleSetSW (CONSOLE_CB *consoleCB, unsigned long arg)
 
STATIC INT32 ConsoleGetWinSize (unsigned long arg)
 
STATIC INT32 ConsoleGetTermios (unsigned long arg)
 
INT32 ConsoleSetPgrp (CONSOLE_CB *consoleCB, unsigned long arg)
 
INT32 ConsoleGetPgrp (CONSOLE_CB *consoleCB, unsigned long arg)
 对控制台i/o操作 更多...
 
STATIC INT32 ConsoleIoctl (struct file *filep, INT32 cmd, unsigned long arg)
 
STATIC INT32 ConsolePoll (struct file *filep, poll_table *fds)
 
STATIC VOID OsConsoleTermiosInit (CONSOLE_CB *consoleCB, const CHAR *deviceName)
 termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口, 通过设置termios类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。 更多...
 
STATIC INT32 OsConsoleFileInit (CONSOLE_CB *consoleCB)
 控制台文件实例初始化 更多...
 
STATIC INT32 OsConsoleDevInit (CONSOLE_CB *consoleCB, const CHAR *deviceName)
 
STATIC UINT32 OsConsoleDevDeinit (const CONSOLE_CB *consoleCB)
 注销控制台设备 更多...
 
STATIC CirBufSendCBConsoleCirBufCreate (VOID)
 创建一个控制台循环buf 更多...
 
STATIC VOID ConsoleCirBufDelete (CirBufSendCB *cirBufSendCB)
 删除循环buf 更多...
 
STATIC UINT32 OsConsoleBufInit (CONSOLE_CB *consoleCB)
 控制台缓存初始化,创建一个 发送任务 更多...
 
STATIC VOID OsConsoleBufDeinit (CONSOLE_CB *consoleCB)
 控制台buf去初始化 更多...
 
STATIC CONSOLE_CBOsConsoleCBInit (UINT32 consoleID)
 控制台描述符初始化 更多...
 
STATIC VOID OsConsoleCBDeinit (CONSOLE_CB *consoleCB)
 释放控制台描述符初始化时所占用的内核空间 更多...
 
STATIC CONSOLE_CBOsConsoleCreate (UINT32 consoleID, const CHAR *deviceName)
 创建一个控制台,这个函数的goto语句贼多 更多...
 
STATIC UINT32 OsConsoleDelete (CONSOLE_CB *consoleCB)
 删除控制台 更多...
 
INT32 system_console_init (const CHAR *deviceName)
 初始化系统控制台并返回 stdinfd stdoutfd stderrfd ,和system_console_deinit成对出现,像控制台的构造函数 更多...
 
INT32 system_console_deinit (const CHAR *deviceName)
 控制台结束前的处理 和 system_console_init成对出现,像控制台的析构函数 更多...
 
BOOL ConsoleEnable (VOID)
 控制台使能 更多...
 
BOOL IsShellEntryRunning (UINT32 shellEntryId)
 
INT32 ConsoleTaskReg (INT32 consoleID, UINT32 taskID)
 任务注册控制台,每个shell任务都有属于自己的控制台 更多...
 
BOOL SetSerialNonBlock (const CONSOLE_CB *consoleCB)
 无锁方式设置串口 更多...
 
BOOL SetSerialBlock (const CONSOLE_CB *consoleCB)
 锁方式设置串口 更多...
 
BOOL SetTelnetNonBlock (const CONSOLE_CB *consoleCB)
 无锁方式设置远程登录 更多...
 
BOOL SetTelnetBlock (const CONSOLE_CB *consoleCB)
 锁方式设置远程登录 更多...
 
BOOL is_nonblock (const CONSOLE_CB *consoleCB)
 
INT32 ConsoleUpdateFd (VOID)
 控制台更新文件句柄 更多...
 
CONSOLE_CBOsGetConsoleByID (INT32 consoleID)
 获取参数控制台ID 获取对应的控制台控制块(描述符) 更多...
 
CONSOLE_CBOsGetConsoleByTaskID (UINT32 taskID)
 获取参数任务的控制台控制块(描述符) 更多...
 
VOID OsSetConsoleID (UINT32 newTaskID, UINT32 curTaskID)
 设置控制台ID 更多...
 
STATIC ssize_t WriteToTerminal (const CONSOLE_CB *consoleCB, const CHAR *buffer, size_t bufLen)
 将buf内容写到终端设备 更多...
 
VOID OsWaitConsoleSendTaskPend (UINT32 taskID)
 
VOID OsWakeConsoleSendTask (VOID)
 唤醒控制台发送任务 更多...
 

变量

UINT32 g_uart_fputc_en
 
STATIC UINT8 g_taskConsoleIDArray [LOSCFG_BASE_CORE_TSK_LIMIT]
 task 控制台ID池,同步task数量,理论上每个task都可以有一个自己的控制台 更多...
 
CONSOLE_CBg_console [CONSOLE_NUM]
 控制台全局变量,控制台是共用的, 默认为 2个 更多...
 
STATIC const struct file_operations_vfs g_consoleDevOps
 

枚举类型说明

◆ anonymous enum

anonymous enum

根据VT终端标准 <ESC>[37m 为设置前景色

枚举值
STAT_NORMAL_KEY 

普通按键

STAT_ESC_KEY 

控制按键,只有 ESC 是

STAT_MULTI_KEY 

多个按键,只有 [ 是

在文件 console.c366 行定义.

366 {
367 STAT_NORMAL_KEY,///< 普通按键
368 STAT_ESC_KEY, ///< 控制按键,只有 ESC 是
369 STAT_MULTI_KEY ///< 多个按键,只有 [ 是
370};
@ STAT_ESC_KEY
控制按键,只有 ESC 是
Definition: console.c:368
@ STAT_NORMAL_KEY
普通按键
Definition: console.c:367
@ STAT_MULTI_KEY
多个按键,只有 [ 是
Definition: console.c:369

函数说明

◆ ConsoleCirBufCreate()

STATIC CirBufSendCB * ConsoleCirBufCreate ( VOID  )

创建一个控制台循环buf

在文件 console.c1144 行定义.

1145{
1146 UINT32 ret;
1147 CHAR *fifo = NULL;
1148 CirBufSendCB *cirBufSendCB = NULL;
1149 CirBuf *cirBufCB = NULL;
1150
1151 cirBufSendCB = (CirBufSendCB *)LOS_MemAlloc(m_aucSysMem0, sizeof(CirBufSendCB));//分配一个循环buf发送控制块
1152 if (cirBufSendCB == NULL) {
1153 return NULL;
1154 }
1155 (VOID)memset_s(cirBufSendCB, sizeof(CirBufSendCB), 0, sizeof(CirBufSendCB));
1156
1157 fifo = (CHAR *)LOS_MemAlloc(m_aucSysMem0, CONSOLE_CIRCBUF_SIZE);//分配FIFO buf 1K
1158 if (fifo == NULL) {
1159 goto ERROR_WITH_SENDCB;
1160 }
1161 (VOID)memset_s(fifo, CONSOLE_CIRCBUF_SIZE, 0, CONSOLE_CIRCBUF_SIZE);
1162
1163 cirBufCB = &cirBufSendCB->cirBufCB;
1164 ret = LOS_CirBufInit(cirBufCB, fifo, CONSOLE_CIRCBUF_SIZE);//环形BUF初始化
1165 if (ret != LOS_OK) {
1166 goto ERROR_WITH_FIFO;
1167 }
1168
1169 (VOID)LOS_EventInit(&cirBufSendCB->sendEvent);//事件初始化
1170 return cirBufSendCB;
1171
1172ERROR_WITH_FIFO:
1173 (VOID)LOS_MemFree(m_aucSysMem0, cirBufCB->fifo);
1174ERROR_WITH_SENDCB:
1175 (VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);
1176 return NULL;
1177}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventInit(PEVENT_CB_S eventCB)
初始化一个事件控制块
Definition: los_event.c:95
VOID * LOS_MemAlloc(VOID *pool, UINT32 size)
从指定内存池中申请size长度的内存,注意这可不是从内核堆空间中申请内存
Definition: los_memory.c:1123
UINT32 LOS_MemFree(VOID *pool, VOID *ptr)
释放从指定动态内存中申请的内存
Definition: los_memory.c:1369
UINT8 * m_aucSysMem0
异常交互动态内存池地址的起始地址,当不支持异常交互特性时,m_aucSysMem0等于m_aucSysMem1。
Definition: los_memory.c:107
UINT32 LOS_CirBufInit(CirBuf *cirbufCB, CHAR *fifo, UINT32 size)
初始化循环buf
Definition: los_cir_buf.c:225
unsigned int UINT32
Definition: los_typedef.h:57
char CHAR
Definition: los_typedef.h:63
CHAR * fifo
Definition: los_cir_buf.h:57
发送环形buf控制块,通过事件发送
Definition: console.h:97
EVENT_CB_S sendEvent
Definition: console.h:99
CirBuf cirBufCB
Definition: console.h:98
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleCirBufDelete()

STATIC VOID ConsoleCirBufDelete ( CirBufSendCB cirBufSendCB)

删除循环buf

在文件 console.c1179 行定义.

1180{
1181 CirBuf *cirBufCB = &cirBufSendCB->cirBufCB;
1182
1183 (VOID)LOS_MemFree(m_aucSysMem0, cirBufCB->fifo);//释放内存 8K
1184 LOS_CirBufDeinit(cirBufCB);//清除初始化操作
1185 (VOID)LOS_EventDestroy(&cirBufSendCB->sendEvent);//销毁事件
1186 (VOID)LOS_MemFree(m_aucSysMem0, cirBufSendCB);//释放循环buf发送控制块
1187}
LITE_OS_SEC_TEXT_INIT UINT32 LOS_EventDestroy(PEVENT_CB_S eventCB)
销毁指定的事件控制块
Definition: los_event.c:334
VOID LOS_CirBufDeinit(CirBuf *cirbufCB)
删除初始化操作,其实就是清0
Definition: los_cir_buf.c:241
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleClose()

STATIC INT32 ConsoleClose ( struct file filep)

关闭控制台

在文件 console.c618 行定义.

619{
620 INT32 ret;
621 struct file *privFilep = NULL;
622 const struct file_operations_vfs *fileOps = NULL;
623
624 ret = GetFilepOps(filep, &privFilep, &fileOps);
625 if (ret != ENOERR) {
626 ret = EINVAL;
627 goto ERROUT;
628 }
629 ret = FilepClose(privFilep, fileOps);
630 if (ret < 0) {
631 ret = EPERM;
632 goto ERROUT;
633 }
634
635 return ENOERR;
636
637ERROUT:
638 set_errno(ret);
639 return VFS_ERROR;
640}
INT32 GetFilepOps(const struct file *filep, struct file **privFilep, const struct file_operations_vfs **filepOps)
Definition: console.c:93
INT32 FilepClose(struct file *filep, const struct file_operations_vfs *fops)
关闭串口或远程登录
Definition: console.c:545
signed int INT32
Definition: los_typedef.h:60
函数调用图:

◆ ConsoleCtrlCaptureChar()

STATIC INT32 ConsoleCtrlCaptureChar ( CONSOLE_CB consoleCB)

铺捉到 ctrl + 右方向键(>)

在文件 console.c192 行定义.

函数调用图:
这是这个函数的调用关系图:

◆ ConsoleCtrlCaptureLine()

STATIC INT32 ConsoleCtrlCaptureLine ( CONSOLE_CB consoleCB)

铺捉到 ctrl + 字符, 例如 ctrl + c

在文件 console.c178 行定义.

函数调用图:
这是这个函数的调用关系图:

◆ ConsoleCtrlRightsCapture()

STATIC INT32 ConsoleCtrlRightsCapture ( CONSOLE_CB consoleCB)

在文件 console.c206 行定义.

207{
208 (VOID)LOS_SemPend(consoleCB->consoleSem, LOS_WAIT_FOREVER);
209 if ((ConsoleRefcountGet(consoleCB) == 0) &&
210 (OsCurrTaskGet()->taskID != consoleCB->shellEntryId)) { //控制台没有任务使用且当前任务不是接收终端输入的shell entry 任务
211 /* not 0:indicate that shellentry is in uart_read, suspend shellentry task directly
212 | 表示shellentry在uart_read中,直接挂起shellentry任务*/
213 (VOID)LOS_TaskSuspend(consoleCB->shellEntryId);//挂起任务,意味着不接受输入
214 }
215 ConsoleRefcountSet(consoleCB, TRUE); //占用控制台
216 return LOS_OK;
217}
STATIC UINT32 ConsoleRefcountGet(const CONSOLE_CB *consoleCB)
Definition: console.c:162
STATIC VOID ConsoleRefcountSet(CONSOLE_CB *consoleCB, BOOL flag)
设置控制台引用次数,也表示占用控制台的数量
Definition: console.c:167
LITE_OS_SEC_TEXT UINT32 LOS_SemPend(UINT32 semHandle, UINT32 timeout)
对外接口 申请指定的信号量,并设置超时时间
Definition: los_sem.c:226
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskSuspend(UINT32 taskID)
外部接口,对OsTaskSuspend的封装
Definition: los_task.c:855
STATIC INLINE LosTaskCB * OsCurrTaskGet(VOID)
UINT32 shellEntryId
负责接受来自终端信息的 "ShellEntry"任务,这个值在运行过程中可能会被换掉,它始终指向当前正在运行的shell客户端
Definition: console.h:114
UINT32 consoleSem
控制台信号量
Definition: console.h:108
UINT32 taskID
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleCtrlRightsRelease()

STATIC INT32 ConsoleCtrlRightsRelease ( CONSOLE_CB consoleCB)

在文件 console.c219 行定义.

220{
221 if (ConsoleRefcountGet(consoleCB) == 0) {
222 PRINT_ERR("console is free\n");
223 (VOID)LOS_SemPost(consoleCB->consoleSem);
224 return LOS_NOK;
225 } else {
226 ConsoleRefcountSet(consoleCB, FALSE);//释放控制台
227 if ((ConsoleRefcountGet(consoleCB) == 0) &&
228 (OsCurrTaskGet()->taskID != consoleCB->shellEntryId)) {
229 (VOID)LOS_TaskResume(consoleCB->shellEntryId);
230 }
231 }
232 (VOID)LOS_SemPost(consoleCB->consoleSem);
233 return LOS_OK;
234}
LITE_OS_SEC_TEXT UINT32 LOS_SemPost(UINT32 semHandle)
对外接口 释放指定的信号量
Definition: los_sem.c:315
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskResume(UINT32 taskID)
恢复挂起的任务,使该任务进入ready状态
Definition: los_task.c:758
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleEnable()

BOOL ConsoleEnable ( VOID  )

控制台使能

ShellEntry是否在运行,其为负责接受来自终端敲入的一个个字符

在文件 console.c1415 行定义.

函数调用图:
这是这个函数的调用关系图:

◆ ConsoleFifoClearup()

STATIC VOID ConsoleFifoClearup ( CONSOLE_CB console)

在文件 console.c306 行定义.

307{
308 console->fifoOut = 0;
309 console->fifoIn = 0;
310 (VOID)memset_s(console->fifo, CONSOLE_FIFO_SIZE, 0, CONSOLE_FIFO_SIZE);
311}
UINT8 fifo[CONSOLE_FIFO_SIZE]
termios 规范模式(ICANON mode )下使用 size:1K
Definition: console.h:122
UINT32 fifoIn
对fifo的标记,输入位置
Definition: console.h:124
UINT32 fifoOut
对fifo的标记,输出位置
Definition: console.h:123
这是这个函数的调用关系图:

◆ ConsoleFifoEmpty()

STATIC BOOL ConsoleFifoEmpty ( const CONSOLE_CB console)

在文件 console.c301 行定义.

302{
303 return console->fifoOut == console->fifoIn;
304}
这是这个函数的调用关系图:

◆ ConsoleFifoLenUpdate()

STATIC VOID ConsoleFifoLenUpdate ( CONSOLE_CB console)

控制台buf长度更新

在文件 console.c313 行定义.

314{
315 console->currentLen = console->fifoIn - console->fifoOut;
316}
UINT32 currentLen
当前fifo位置
Definition: console.h:125
这是这个函数的调用关系图:

◆ ConsoleGetPgrp()

INT32 ConsoleGetPgrp ( CONSOLE_CB consoleCB,
unsigned long  arg 
)

对控制台i/o操作

在文件 console.c881 行定义.

函数调用图:
这是这个函数的调用关系图:

◆ ConsoleGetTermios()

STATIC INT32 ConsoleGetTermios ( unsigned long  arg)

在文件 console.c854 行定义.

855{
856 struct file *filep = NULL;
857 CONSOLE_CB *consoleCB = NULL;
858
859 INT32 ret = fs_getfilep(0, &filep);
860 if (ret < 0) {
861 return -EPERM;
862 }
863
864 consoleCB = (CONSOLE_CB *)filep->f_priv;
865 if (consoleCB == NULL) {
866 return -EFAULT;
867 }
868
869 return (LOS_ArchCopyToUser((VOID *)arg, &consoleCB->consoleTermios, sizeof(struct termios)) != 0) ?
870 -EFAULT : LOS_OK;
871}
控制台控制块(描述符)
Definition: console.h:105
struct termios consoleTermios
行规程
Definition: console.h:126
void * f_priv
if(tv==NULL)
Definition: time.c:430
size_t LOS_ArchCopyToUser(void *dst, const void *src, size_t len)
从内核空间拷贝到用户空间
Definition: user_copy.c:79
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleGetWinSize()

STATIC INT32 ConsoleGetWinSize ( unsigned long  arg)

在文件 console.c843 行定义.

844{
845 struct winsize kws = {
846 .ws_col = DEFAULT_WINDOW_SIZE_COL,
847 .ws_row = DEFAULT_WINDOW_SIZE_ROW
848 };
849
850 return (LOS_CopyFromKernel((VOID *)arg, sizeof(struct winsize), &kws, sizeof(struct winsize)) != 0) ?
851 -EFAULT : LOS_OK;
852}
INT32 LOS_CopyFromKernel(VOID *dest, UINT32 max, const VOID *src, UINT32 count)
将内核数据拷贝到用户空间
Definition: user_copy.c:88
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleIoctl()

STATIC INT32 ConsoleIoctl ( struct file filep,
INT32  cmd,
unsigned long  arg 
)

在文件 console.c887 行定义.

888{
889 INT32 ret;
890 struct file *privFilep = NULL;
891 CONSOLE_CB *consoleCB = NULL;
892 const struct file_operations_vfs *fileOps = NULL;
893
894 ret = GetFilepOps(filep, &privFilep, &fileOps);
895 if (ret != ENOERR) {
896 ret = EINVAL;
897 goto ERROUT;
898 }
899
900 if (fileOps->ioctl == NULL) {
901 ret = EFAULT;
902 goto ERROUT;
903 }
904
905 consoleCB = (CONSOLE_CB *)filep->f_priv;
906 if (consoleCB == NULL) {
907 ret = EINVAL;
908 goto ERROUT;
909 }
910
911 switch (cmd) {
912 case CONSOLE_CONTROL_RIGHTS_CAPTURE:
913 ret = ConsoleCtrlRightsCapture(consoleCB);
914 break;
915 case CONSOLE_CONTROL_RIGHTS_RELEASE:
916 ret = ConsoleCtrlRightsRelease(consoleCB);
917 break;
918 case CONSOLE_CONTROL_CAPTURE_LINE:
919 ret = ConsoleCtrlCaptureLine(consoleCB);
920 break;
921 case CONSOLE_CONTROL_CAPTURE_CHAR:
922 ret = ConsoleCtrlCaptureChar(consoleCB);
923 break;
924 case CONSOLE_CONTROL_REG_USERTASK: //注册shell 客户端 http://weharmonyos.com/blog/72.html
925 ret = ConsoleTaskReg(consoleCB->consoleID, arg);
926 break;
927 case TIOCGWINSZ:
928 ret = ConsoleGetWinSize(arg);
929 break;
930 case TCSETSW:
931 ret = ConsoleSetSW(consoleCB, arg);
932 break;
933 case TCGETS:
934 ret = ConsoleGetTermios(arg);
935 break;
936 case TIOCGPGRP:
937 ret = ConsoleGetPgrp(consoleCB, arg);
938 break;
939 case TIOCSPGRP:
940 ret = ConsoleSetPgrp(consoleCB, arg);
941 break;
942 default:
943 if ((cmd == UART_CFG_ATTR || cmd == UART_CFG_PRIVATE)
944 && !LOS_IsUserAddress(arg)) {
945 ret = EINVAL;
946 goto ERROUT;
947 }
948 ret = fileOps->ioctl(privFilep, cmd, arg);
949 break;
950 }
951
952 if (ret < 0) {
953 ret = EPERM;
954 goto ERROUT;
955 }
956
957 return ret;
958ERROUT:
959 set_errno(ret);
960 return VFS_ERROR;
961}
INT32 ConsoleTaskReg(INT32 consoleID, UINT32 taskID)
任务注册控制台,每个shell任务都有属于自己的控制台
Definition: console.c:1454
STATIC INT32 ConsoleSetSW(CONSOLE_CB *consoleCB, unsigned long arg)
Definition: console.c:826
STATIC INT32 ConsoleCtrlCaptureChar(CONSOLE_CB *consoleCB)
铺捉到 ctrl + 右方向键(>)
Definition: console.c:192
STATIC INT32 ConsoleGetWinSize(unsigned long arg)
Definition: console.c:843
STATIC INT32 ConsoleCtrlRightsCapture(CONSOLE_CB *consoleCB)
Definition: console.c:206
STATIC INT32 ConsoleGetTermios(unsigned long arg)
Definition: console.c:854
INT32 ConsoleSetPgrp(CONSOLE_CB *consoleCB, unsigned long arg)
Definition: console.c:873
STATIC INT32 ConsoleCtrlCaptureLine(CONSOLE_CB *consoleCB)
铺捉到 ctrl + 字符, 例如 ctrl + c
Definition: console.c:178
STATIC INT32 ConsoleCtrlRightsRelease(CONSOLE_CB *consoleCB)
Definition: console.c:219
INT32 ConsoleGetPgrp(CONSOLE_CB *consoleCB, unsigned long arg)
对控制台i/o操作
Definition: console.c:881
STATIC INLINE BOOL LOS_IsUserAddress(VADDR_T vaddr)
虚拟地址是否在用户空间
Definition: los_vm_map.h:275
UINT32 consoleID
控制台ID 例如 : 1 | 串口 , 2 | 远程登录
Definition: console.h:106
函数调用图:

◆ ConsoleOpen()

STATIC INT32 ConsoleOpen ( struct file filep)

对 file_operations_vfs->open 的实现函数,也就是说这是 打开控制台的实体函数.

在文件 console.c587 行定义.

588{
589 INT32 ret;
590 UINT32 consoleID;
591 struct file *privFilep = NULL;
592 const struct file_operations_vfs *fileOps = NULL;
593
594 consoleID = (UINT32)OsConsoleFullpathToID(filep->f_path);//先找到控制台ID返回 (1,2,-1)
595 if (consoleID == (UINT32)-1) {
596 ret = EPERM;
597 goto ERROUT;
598 }
599 filep->f_priv = g_console[consoleID - 1]; //f_priv 每种文件系统对应结构体都同,所以是void的类型,如一张白纸,画什么模块自己定
600
601 ret = GetFilepOps(filep, &privFilep, &fileOps);//获取文件系统的驱动程序
602 if (ret != ENOERR) {
603 ret = EINVAL;
604 goto ERROUT;
605 }
606 ret = FilepOpen(privFilep, fileOps);//打开文件,其实调用的是 串口底层驱动程序
607 if (ret < 0) {
608 ret = EPERM;
609 goto ERROUT;
610 }
611 return ENOERR;
612
613ERROUT:
614 set_errno(ret);
615 return VFS_ERROR;
616}
INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops)
打开串口或远程登录
Definition: console.c:337
STATIC INT32 OsConsoleFullpathToID(const CHAR *fullpath)
通过路径找到控制台ID
Definition: console.c:276
CONSOLE_CB * g_console[CONSOLE_NUM]
控制台全局变量,控制台是共用的, 默认为 2个
Definition: console.c:80
char * f_path
函数调用图:

◆ ConsolePoll()

STATIC INT32 ConsolePoll ( struct file filep,
poll_table *  fds 
)

在文件 console.c963 行定义.

964{
965 INT32 ret;
966 struct file *privFilep = NULL;
967 const struct file_operations_vfs *fileOps = NULL;
968
969 ret = GetFilepOps(filep, &privFilep, &fileOps);
970 if (ret != ENOERR) {
971 ret = EINVAL;
972 goto ERROUT;
973 }
974
975 ret = FilepPoll(privFilep, fileOps, fds);
976 if (ret < 0) {
977 ret = EPERM;
978 goto ERROUT;
979 }
980 return ret;
981
982ERROUT:
983 set_errno(ret);
984 return VFS_ERROR;
985}
INT32 FilepPoll(struct file *filep, const struct file_operations_vfs *fops, poll_table *fds)
Definition: console.c:571
函数调用图:

◆ ConsoleRead()

STATIC ssize_t ConsoleRead ( struct file filep,
CHAR buffer,
size_t  bufLen 
)

任务从控制台读数据,例如 Shell Entry 任务会从此读数据

在文件 console.c663 行定义.

664{
665 INT32 ret;
666 struct file *privFilep = NULL;
667 CONSOLE_CB *consoleCB = NULL;
668 CHAR *sbuffer = NULL;
669 BOOL userBuf = FALSE;
670 const struct file_operations_vfs *fileOps = NULL;
671
672 if ((buffer == NULL) || (bufLen == 0)) {
673 ret = EINVAL;
674 goto ERROUT;
675 }
676
677 if (bufLen > CONSOLE_FIFO_SIZE) {
678 bufLen = CONSOLE_FIFO_SIZE;
679 }
680 //检查buffer是否在用户区
681 userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
682 ret = GetFilepOps(filep, &privFilep, &fileOps);
683 if (ret != ENOERR) {
684 ret = -EINVAL;
685 goto ERROUT;
686 }
687 consoleCB = (CONSOLE_CB *)filep->f_priv;
688 if (consoleCB == NULL) {
689 consoleCB = OsGetConsoleByTaskID(OsCurrTaskGet()->taskID);
690 if (consoleCB == NULL) {
691 return -EFAULT;
692 }
693 }
694
695 /*
696 * shell task use FilepRead function to get data,
697 * user task use UserFilepRead to get data
698 */
699 sbuffer = userBuf ? LOS_MemAlloc(m_aucSysMem0, bufLen) : buffer;
700 if (sbuffer == NULL) {
701 ret = -ENOMEM;
702 goto ERROUT;
703 }
704
705 ret = DoRead(consoleCB, sbuffer, bufLen, privFilep, fileOps);//从 console buf中取数据
706 if (ret < 0) {
707 goto ERROUT;
708 }
709
710 if (userBuf) {
711 if (LOS_ArchCopyToUser(buffer, sbuffer, bufLen) != 0) {
712 ret = -EFAULT;
713 goto ERROUT;
714 }
715
716 LOS_MemFree(m_aucSysMem0, sbuffer);
717 }
718
719 return ret;
720
721ERROUT:
722 if ((userBuf) && (sbuffer != NULL)) {
723 LOS_MemFree(m_aucSysMem0, sbuffer);
724 }
725 set_errno(-ret);
726 return VFS_ERROR;
727}
CONSOLE_CB * OsGetConsoleByTaskID(UINT32 taskID)
获取参数任务的控制台控制块(描述符)
Definition: console.c:1554
STATIC ssize_t DoRead(CONSOLE_CB *consoleCB, CHAR *buffer, size_t bufLen, struct file *privFilep, const struct file_operations_vfs *fileOps)
Definition: console.c:642
unsigned long vaddr_t
Definition: los_typedef.h:206
unsigned long UINTPTR
Definition: los_typedef.h:68
size_t BOOL
Definition: los_typedef.h:88
STATIC INLINE BOOL LOS_IsUserAddressRange(VADDR_T vaddr, size_t len)
虚拟地址[vaddr,vaddr + len]是否在用户空间
Definition: los_vm_map.h:281
函数调用图:

◆ ConsoleReadFifo()

STATIC INT32 ConsoleReadFifo ( CHAR buffer,
CONSOLE_CB console,
size_t  bufLen 
)

读取

在文件 console.c318 行定义.

319{
320 INT32 ret;
321 UINT32 readNum;
322
323 readNum = MIN(bufLen, console->currentLen);
324 ret = memcpy_s(buffer, bufLen, console->fifo + console->fifoOut, readNum);
325 if (ret != EOK) {
326 PRINTK("%s,%d memcpy_s failed\n", __FUNCTION__, __LINE__);
327 return -1;
328 }
329 console->fifoOut += readNum;
330 if (ConsoleFifoEmpty(console)) {
331 ConsoleFifoClearup(console);
332 }
333 ConsoleFifoLenUpdate(console);
334 return (INT32)readNum;
335}
STATIC VOID ConsoleFifoClearup(CONSOLE_CB *console)
Definition: console.c:306
STATIC VOID ConsoleFifoLenUpdate(CONSOLE_CB *console)
控制台buf长度更新
Definition: console.c:313
STATIC BOOL ConsoleFifoEmpty(const CONSOLE_CB *console)
Definition: console.c:301
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleRefcountGet()

STATIC UINT32 ConsoleRefcountGet ( const CONSOLE_CB consoleCB)

在文件 console.c162 行定义.

163{
164 return consoleCB->refCount;
165}
UINT32 refCount
引用次数,用于判断控制台是否被占用
Definition: console.h:113
这是这个函数的调用关系图:

◆ ConsoleRefcountSet()

STATIC VOID ConsoleRefcountSet ( CONSOLE_CB consoleCB,
BOOL  flag 
)

设置控制台引用次数,也表示占用控制台的数量

在文件 console.c167 行定义.

168{
169 (consoleCB->refCount) += flag ? 1 : -1;
170}
这是这个函数的调用关系图:

◆ ConsoleSendTask()

STATIC UINT32 ConsoleSendTask ( UINTPTR  param)

控制台发送任务

在文件 console.c1595 行定义.

1596{
1597 CONSOLE_CB *consoleCB = (CONSOLE_CB *)param;
1598 CirBufSendCB *cirBufSendCB = consoleCB->cirBufSendCB;
1599 CirBuf *cirBufCB = &cirBufSendCB->cirBufCB;
1600 UINT32 ret, size;
1601 CHAR *buf = NULL;
1602
1603 (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_RUNNING);//发送一个控制台任务正在运行的事件
1604
1605 while (1) {//读取 CONSOLE_CIRBUF_EVENT | CONSOLE_SEND_TASK_EXIT 这两个事件
1606 ret = LOS_EventRead(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT | CONSOLE_SEND_TASK_EXIT,
1607 LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);//读取循环buf或任务退出的事件
1608 if (ret == CONSOLE_CIRBUF_EVENT) {//控制台循环buf事件发生
1609 size = LOS_CirBufUsedSize(cirBufCB);//循环buf使用大小
1610 if (size == 0) {
1611 continue;
1612 }
1613 buf = (CHAR *)LOS_MemAlloc(m_aucSysMem1, size + 1);//分配接收cirbuf的内存
1614 if (buf == NULL) {
1615 continue;
1616 }
1617 (VOID)memset_s(buf, size + 1, 0, size + 1);//清0
1618
1619 (VOID)LOS_CirBufRead(cirBufCB, buf, size);//读取循环cirBufCB至 buf
1620
1621 (VOID)WriteToTerminal(consoleCB, buf, size);//将buf数据写到控制台终端设备
1622 (VOID)LOS_MemFree(m_aucSysMem1, buf);//清除buf
1623 } else if (ret == CONSOLE_SEND_TASK_EXIT) {//收到任务退出的事件, 由 OsConsoleBufDeinit 发出事件.
1624 break;//退出循环
1625 }
1626 }
1627
1628 ConsoleCirBufDelete(cirBufSendCB);//删除循环buf,归还内存
1629 return LOS_OK;
1630}
STATIC VOID ConsoleCirBufDelete(CirBufSendCB *cirBufSendCB)
删除循环buf
Definition: console.c:1179
STATIC ssize_t WriteToTerminal(const CONSOLE_CB *consoleCB, const CHAR *buffer, size_t bufLen)
将buf内容写到终端设备
Definition: console.c:1570
LITE_OS_SEC_TEXT UINT32 LOS_EventRead(PEVENT_CB_S eventCB, UINT32 eventMask, UINT32 mode, UINT32 timeout)
读取指定事件类型,超时时间为相对时间:单位为Tick
Definition: los_event.c:313
LITE_OS_SEC_TEXT UINT32 LOS_EventWrite(PEVENT_CB_S eventCB, UINT32 events)
写指定的事件类型
Definition: los_event.c:318
UINT8 * m_aucSysMem1
系统动态内存池地址的起始地址 @note_thinking 能否不要用 0,1来命名核心变量 ???
Definition: los_memory.c:108
UINT32 LOS_CirBufRead(CirBuf *cirbufCB, CHAR *buf, UINT32 size)
读取循环buf的数据
Definition: los_cir_buf.c:199
UINT32 LOS_CirBufUsedSize(CirBuf *cirbufCB)
返回循环buf已使用的大小
Definition: los_cir_buf.c:37
CirBufSendCB * cirBufSendCB
循环缓冲发送控制块
Definition: console.h:121
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleSetPgrp()

INT32 ConsoleSetPgrp ( CONSOLE_CB consoleCB,
unsigned long  arg 
)

在文件 console.c873 行定义.

874{
875 if (LOS_ArchCopyFromUser(&consoleCB->pgrpId, (INT32 *)(UINTPTR)arg, sizeof(INT32)) != 0) {
876 return -EFAULT;
877 }
878 return LOS_OK;
879}
INT32 pgrpId
进程组ID
Definition: console.h:115
size_t LOS_ArchCopyFromUser(void *dst, const void *src, size_t len)
Definition: user_copy.c:58
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleSetSW()

STATIC INT32 ConsoleSetSW ( CONSOLE_CB consoleCB,
unsigned long  arg 
)

在文件 console.c826 行定义.

827{
828 struct termios kerTermios;
829 UINT32 intSave;
830
831 if (LOS_ArchCopyFromUser(&kerTermios, (struct termios *)arg, sizeof(struct termios)) != 0) {
832 return -EFAULT;
833 }
834
835 LOS_SpinLockSave(&g_consoleSpin, &intSave);
836 (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &kerTermios);
837 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
838 return LOS_OK;
839}
INT32 ConsoleTcSetAttr(INT32 fd, INT32 actions, const struct termios *termios)
设置控制台 模式值
Definition: console.c:141
VOID LOS_SpinUnlockRestore(SPIN_LOCK_S *lock, UINT32 intSave)
Definition: los_spinlock.c:108
VOID LOS_SpinLockSave(SPIN_LOCK_S *lock, UINT32 *intSave)
Definition: los_spinlock.c:98
INT32 fd
系统文件句柄, 由内核分配
Definition: console.h:112
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleTaskReg()

INT32 ConsoleTaskReg ( INT32  consoleID,
UINT32  taskID 
)

任务注册控制台,每个shell任务都有属于自己的控制台

在文件 console.c1454 行定义.

1455{
1456 UINT32 intSave;
1457
1458 LOS_SpinLockSave(&g_consoleSpin, &intSave);
1459 if (!IsShellEntryRunning(g_console[consoleID - 1]->shellEntryId)) {//如果控制台还没有捆绑shell客户端任务
1460 g_console[consoleID - 1]->shellEntryId = taskID; //给控制台捆绑一个shell客户端任务,接受终端输入.
1461 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1462 (VOID)OsSetCurrProcessGroupID(OsGetUserInitProcessID());// @notethinking 为何要在此处设置当前进程的组ID?
1463 return LOS_OK;
1464 }
1465 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1466 return (g_console[consoleID - 1]->shellEntryId == taskID) ? LOS_OK : LOS_NOK;
1467}
BOOL IsShellEntryRunning(UINT32 shellEntryId)
Definition: console.c:1442
LITE_OS_SEC_TEXT UINT32 OsGetUserInitProcessID(VOID)
获取用户态进程的根进程,所有用户进程都是g_processCBArray[g_userInitProcess] fork来的
Definition: los_process.c:2244
LITE_OS_SEC_TEXT INT32 OsSetCurrProcessGroupID(UINT32 gid)
Definition: los_process.c:1456
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleTcGetAttr()

INT32 ConsoleTcGetAttr ( INT32  fd,
struct termios *  termios 
)

获取控制台 模式值

在文件 console.c122 行定义.

123{
124 struct file *filep = NULL;
125 CONSOLE_CB *consoleCB = NULL;
126
127 INT32 ret = fs_getfilep(fd, &filep);
128 if (ret < 0) {
129 return -EPERM;
130 }
131
132 consoleCB = (CONSOLE_CB *)filep->f_priv;
133 if (consoleCB == NULL) {
134 return -EFAULT;
135 }
136
137 (VOID)memcpy_s(termios, sizeof(struct termios), &consoleCB->consoleTermios, sizeof(struct termios));
138 return LOS_OK;
139}
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleTcSetAttr()

INT32 ConsoleTcSetAttr ( INT32  fd,
INT32  actions,
const struct termios *  termios 
)

设置控制台 模式值

在文件 console.c141 行定义.

142{
143 struct file *filep = NULL;
144 CONSOLE_CB *consoleCB = NULL;
145
146 (VOID)actions;
147
148 INT32 ret = fs_getfilep(fd, &filep);
149 if (ret < 0) {
150 return -EPERM;
151 }
152
153 consoleCB = (CONSOLE_CB *)filep->f_priv;
154 if (consoleCB == NULL) {
155 return -EFAULT;
156 }
157
158 (VOID)memcpy_s(&consoleCB->consoleTermios, sizeof(struct termios), termios, sizeof(struct termios));
159 return LOS_OK;
160}
函数调用图:
这是这个函数的调用关系图:

◆ ConsoleUpdateFd()

INT32 ConsoleUpdateFd ( VOID  )

控制台更新文件句柄

在文件 console.c1517 行定义.

1518{
1519 INT32 consoleID;
1520
1521 if (OsCurrTaskGet() != NULL) {
1522 consoleID = g_taskConsoleIDArray[(OsCurrTaskGet())->taskID];//获取当前任务的控制台 (1,2,-1)
1523 } else {
1524 return -1;
1525 }
1526
1527 if (g_uart_fputc_en == 0) {
1528 if (g_console[CONSOLE_TELNET - 1] != NULL) {
1529 consoleID = CONSOLE_TELNET;
1530 }
1531 } else if (consoleID == 0) {
1532 if (g_console[CONSOLE_SERIAL - 1] != NULL) {
1533 consoleID = CONSOLE_SERIAL;
1534 } else if (g_console[CONSOLE_TELNET - 1] != NULL) {
1535 consoleID = CONSOLE_TELNET;
1536 } else {
1537 PRINTK("No console dev used.\n");
1538 return -1;
1539 }
1540 }
1541
1542 return (g_console[consoleID - 1] != NULL) ? g_console[consoleID - 1]->fd : -1;
1543}
STATIC UINT8 g_taskConsoleIDArray[LOSCFG_BASE_CORE_TSK_LIMIT]
task 控制台ID池,同步task数量,理论上每个task都可以有一个自己的控制台
Definition: console.c:68
UINT32 g_uart_fputc_en
函数调用图:

◆ ConsoleWrite()

STATIC ssize_t ConsoleWrite ( struct file filep,
const CHAR buffer,
size_t  bufLen 
)

用户任务写数据到控制台

在文件 console.c767 行定义.

768{
769 INT32 ret;
770 CHAR *sbuffer = NULL;
771 BOOL userBuf = FALSE;
772 CirBufSendCB *cirBufSendCB = NULL;
773 struct file *privFilep = NULL;
774 const struct file_operations_vfs *fileOps = NULL;
775
776 if ((buffer == NULL) || (bufLen == 0)) {
777 ret = EINVAL;
778 goto ERROUT;
779 }
780
781 if (bufLen > CONSOLE_FIFO_SIZE) {
782 bufLen = CONSOLE_FIFO_SIZE;
783 }
784 //检测buffer是否在用户空间
785 userBuf = LOS_IsUserAddressRange((vaddr_t)(UINTPTR)buffer, bufLen);
786
787 ret = GetFilepOps(filep, &privFilep, &fileOps);
788 if ((ret != ENOERR) || (fileOps->write == NULL) || (filep->f_priv == NULL)) {
789 ret = EINVAL;
790 goto ERROUT;
791 }
792 cirBufSendCB = ((CONSOLE_CB *)filep->f_priv)->cirBufSendCB;
793
794 /*
795 * adopt uart open function to read data from buffer | 用uart open函数从buffer中读取数据
796 * and write data to filep (filep is | 向filep写入数据(filep对应/dev/console的filep)
797 * corresponding to filep of /dev/console)
798 */
799 sbuffer = userBuf ? LOS_MemAlloc(m_aucSysMem0, bufLen) : (CHAR *)buffer;
800 if (sbuffer == NULL) {
801 ret = ENOMEM;
802 goto ERROUT;
803 }
804 //将用户空间的数据拷贝进内核空间
805 if (userBuf && (LOS_ArchCopyFromUser(sbuffer, buffer, bufLen) != 0)) {
806 ret = EFAULT;
807 goto ERROUT;
808 }
809 ret = DoWrite(cirBufSendCB, sbuffer, bufLen);//真正的写操作,向控制台任务发起写入事件
810
811 if (userBuf) {
812 LOS_MemFree(m_aucSysMem0, sbuffer);
813 }
814
815 return ret;
816
817ERROUT:
818 if (userBuf && sbuffer != NULL) {
819 LOS_MemFree(m_aucSysMem0, sbuffer);
820 }
821
822 set_errno(ret);
823 return VFS_ERROR;
824}
STATIC ssize_t DoWrite(CirBufSendCB *cirBufSendCB, CHAR *buffer, size_t bufLen)
Definition: console.c:729
函数调用图:

◆ DoRead()

STATIC ssize_t DoRead ( CONSOLE_CB consoleCB,
CHAR buffer,
size_t  bufLen,
struct file privFilep,
const struct file_operations_vfs *  fileOps 
)

在文件 console.c642 行定义.

645{
646 INT32 ret;
647
648#ifdef LOSCFG_SHELL
649 if (OsCurrTaskGet()->taskID == consoleCB->shellEntryId) {//shell Entry 任务读取内容
650 ret = FilepRead(privFilep, fileOps, buffer, bufLen);//直接从串口中读数据
651 } else {//其他任务读取内容,需经过行规程处理
652#endif
653 (VOID)ConsoleCtrlRightsCapture(consoleCB);
654 ret = UserFilepRead(consoleCB, privFilep, fileOps, buffer, bufLen);
655 (VOID)ConsoleCtrlRightsRelease(consoleCB);
656#ifdef LOSCFG_SHELL
657 }
658#endif
659
660 return ret;
661}
STATIC INT32 UserFilepRead(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
使用参数buffer将控制台的buf接走
Definition: console.c:455
INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
从串口或远程登录中读数据
Definition: console.c:517
函数调用图:
这是这个函数的调用关系图:

◆ DoWrite()

STATIC ssize_t DoWrite ( CirBufSendCB cirBufSendCB,
CHAR buffer,
size_t  bufLen 
)

在文件 console.c729 行定义.

730{
731 INT32 cnt;
732 size_t written = 0;
733 size_t toWrite = bufLen;
734 UINT32 intSave;
735
736#ifdef LOSCFG_SHELL_DMESG
737 (VOID)OsLogMemcpyRecord(buffer, bufLen); //同时写到内核缓冲区中,这也导致 OHOS# dmesg 会输出相同的内容
738 if (OsCheckConsoleLock()) {
739 return 0;
740 }
741#endif
742
743 LOS_SpinLockSave(&g_consoleWriteSpinLock, &intSave);
744 while (written < (INT32)bufLen) {
745 /* Transform for CR/LR mode | 回车(CR, ASCII 13, \r) 换行(LF, ASCII 10, \n)*/
746 if ((buffer[written] == '\n') || (buffer[written] == '\r')) {
747 (VOID)LOS_CirBufWrite(&cirBufSendCB->cirBufCB, "\r", 1);
748 }
749
750 cnt = LOS_CirBufWrite(&cirBufSendCB->cirBufCB, &buffer[written], 1);
751 if (cnt <= 0) {
752 break;
753 }
754 toWrite -= cnt;
755 written += cnt;
756 }
757 LOS_SpinUnlockRestore(&g_consoleWriteSpinLock, intSave);
758
759 /* Log is cached but not printed when a system exception occurs */
760 if (OsGetSystemStatus() == OS_SYSTEM_NORMAL) {
761 (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);//发送数据事件
762 }
763
764 return written;
765}
INT32 OsLogMemcpyRecord(const CHAR *buf, UINT32 logLen)
内存拷贝日志
Definition: dmesg.c:508
UINT32 OsCheckConsoleLock(VOID)
Definition: dmesg.c:323
UINT32 LOS_CirBufWrite(CirBuf *cirbufCB, const CHAR *buf, UINT32 size)
写入数据到循环buf区
Definition: los_cir_buf.c:112
UINT32 OsGetSystemStatus(VOID)
获取系统状态
Definition: los_exc.c:181
函数调用图:
这是这个函数的调用关系图:

◆ EchoToTerminal()

STATIC VOID EchoToTerminal ( CONSOLE_CB consoleCB,
struct file filep,
const struct file_operations_vfs *  fops,
char  ch 
)

输出到终端

在文件 console.c417 行定义.

418{
419 if (consoleCB->consoleTermios.c_lflag & ECHO) {
420 if (ch == '\b') {//遇到回退字符
421 (VOID)fops->write(filep, "\b \b", 3);//回退
422 } else {
423 (VOID)fops->write(filep, &ch, EACH_CHAR);//向终端写入字符
424 }
425 }
426}
这是这个函数的调用关系图:

◆ FilepClose()

INT32 FilepClose ( struct file filep,
const struct file_operations_vfs *  fops 
)

关闭串口或远程登录

在文件 console.c545 行定义.

546{
547 INT32 ret;
548 if ((fops == NULL) || (fops->close == NULL)) {
549 return -EFAULT;
550 }
551
552 /*
553 * adopt uart close function to open filep (filep is
554 * corresponding to filep of /dev/console)
555 */
556 ret = fops->close(filep);
557 return ret < 0 ? -EPERM : ret;
558}
这是这个函数的调用关系图:

◆ FilepIoctl()

INT32 FilepIoctl ( struct file filep,
const struct file_operations_vfs *  fops,
INT32  cmd,
unsigned long  arg 
)

在文件 console.c560 行定义.

561{
562 INT32 ret;
563 if (fops->ioctl == NULL) {
564 return -EFAULT;
565 }
566
567 ret = fops->ioctl(filep, cmd, arg);
568 return (ret < 0) ? -EPERM : ret;
569}
这是这个函数的调用关系图:

◆ FilepOpen()

INT32 FilepOpen ( struct file filep,
const struct file_operations_vfs *  fops 
)

打开串口或远程登录

在文件 console.c337 行定义.

338{
339 INT32 ret;
340 if (fops->open == NULL) {
341 return -EFAULT;
342 }
343 //使用 uart open函数打开filep(filep是对应 /dev/console 的 filep)
344 /*
345 * adopt uart open function to open filep (filep is
346 * corresponding to filep of /dev/console)
347 */
348 ret = fops->open(filep);
349 return (ret < 0) ? -EPERM : ret;
350}
这是这个函数的调用关系图:

◆ FilepPoll()

INT32 FilepPoll ( struct file filep,
const struct file_operations_vfs *  fops,
poll_table *  fds 
)

在文件 console.c571 行定义.

572{
573 INT32 ret;
574 if (fops->poll == NULL) {
575 return -EFAULT;
576 }
577
578 /*
579 * adopt uart poll function to poll filep (filep is
580 * corresponding to filep of /dev/serial)
581 */
582 ret = fops->poll(filep, fds);
583 return (ret < 0) ? -EPERM : ret;
584}
这是这个函数的调用关系图:

◆ FilepRead()

INT32 FilepRead ( struct file filep,
const struct file_operations_vfs *  fops,
CHAR buffer,
size_t  bufLen 
)

从串口或远程登录中读数据

在文件 console.c517 行定义.

518{
519 INT32 ret;
520 if (fops->read == NULL) {
521 return -EFAULT;
522 }
523 /*
524 * adopt uart read function to read data from filep
525 * and write data to buffer (filep is
526 * corresponding to filep of /dev/console)
527 *///采用uart read函数从文件中读取数据,将数据写入缓冲区(文件对应/dev/console的filep)
528 ret = fops->read(filep, buffer, bufLen);
529 return (ret < 0) ? -EPERM : ret;
530}
这是这个函数的调用关系图:

◆ FilepWrite()

INT32 FilepWrite ( struct file filep,
const struct file_operations_vfs *  fops,
const CHAR buffer,
size_t  bufLen 
)

写数据到串口或远程登录

在文件 console.c533 行定义.

534{
535 INT32 ret;
536 if (fops->write == NULL) {
537 return -EFAULT;
538 }
539
540 ret = fops->write(filep, buffer, bufLen);
541 return (ret < 0) ? -EPERM : ret;
542}
这是这个函数的调用关系图:

◆ GetFilepOps()

INT32 GetFilepOps ( const struct file filep,
struct file **  privFilep,
const struct file_operations_vfs **  filepOps 
)

在文件 console.c93 行定义.

94{
95 INT32 ret;
96
97 if ((filep == NULL) || (filep->f_vnode == NULL) || (filep->f_vnode->data == NULL)) {
98 ret = EINVAL;
99 goto ERROUT;
100 }
101 //通过 is_private 查找控制台设备的文件(现在是 *privFile)
102 /* to find console device's filep(now it is *privFilep) throught i_private */
103 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
104 *privFilep = (struct file *)drv->priv;// file 例如 g_serialFilep
105 if (((*privFilep)->f_vnode == NULL) || ((*privFilep)->f_vnode->data == NULL)) {
106 ret = EINVAL;
107 goto ERROUT;
108 }
109
110 /* to find uart driver operation function throutht u.i_opss */
111
112 drv = (struct drv_data *)(*privFilep)->f_vnode->data;
113
114 *filepOps = (const struct file_operations_vfs *)drv->ops;//拿到串口驱动程序
115
116 return ENOERR;
117ERROUT:
118 set_errno(ret);
119 return VFS_ERROR;
120}
这是这个函数的调用关系图:

◆ is_nonblock()

BOOL is_nonblock ( const CONSOLE_CB consoleCB)

在文件 console.c1508 行定义.

1509{
1510 if (consoleCB == NULL) {
1511 PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1512 return FALSE;
1513 }
1514 return consoleCB->isNonBlock;
1515}
BOOL isNonBlock
是否无锁方式
Definition: console.h:116
这是这个函数的调用关系图:

◆ IsConsoleOccupied()

BOOL IsConsoleOccupied ( const CONSOLE_CB consoleCB)

控制台是否被占用

在文件 console.c173 行定义.

174{
175 return ConsoleRefcountGet(consoleCB);
176}
函数调用图:
这是这个函数的调用关系图:

◆ IsNeedContinue()

STATIC INT32 IsNeedContinue ( CONSOLE_CB consoleCB,
char  ch,
INT32 lastTokenType 
)

是否需要继续

在文件 console.c407 行定义.

408{
409 if (((ch == '\b') && (consoleCB->consoleTermios.c_lflag & ECHO) && (ConsoleFifoEmpty(consoleCB))) ||
410 (UserShellCheckUDRL(ch, lastTokenType) == LOS_OK)) { /* parse the up/down/right/left key */
411 return LOS_NOK;
412 }
413
414 return LOS_OK;
415}
STATIC INT32 UserShellCheckUDRL(const CHAR ch, INT32 *lastTokenType)
用户shell检查上下左右键
Definition: console.c:372
函数调用图:
这是这个函数的调用关系图:

◆ IsShellEntryRunning()

BOOL IsShellEntryRunning ( UINT32  shellEntryId)

在文件 console.c1442 行定义.

1443{
1444 LosTaskCB *taskCB = NULL;
1445 if (shellEntryId == SHELL_ENTRYID_INVALID) {
1446 return FALSE;
1447 }
1448 taskCB = OsGetTaskCB(shellEntryId);//获取任务
1449 return !OsTaskIsUnused(taskCB) && //确定名为"ShellEntry"的任务
1450 (strlen(taskCB->taskName) == SHELL_ENTRY_NAME_LEN &&
1451 strncmp(taskCB->taskName, SHELL_ENTRY_NAME, SHELL_ENTRY_NAME_LEN) == 0);
1452}
STATIC INLINE LosTaskCB * OsGetTaskCB(UINT32 taskID)
通过任务ID获取任务实体,task由任务池分配,本质是个数组,彼此都挨在一块
Definition: los_task_pri.h:250
STATIC INLINE BOOL OsTaskIsUnused(const LosTaskCB *taskCB)
任务是否在使用
Definition: los_task_pri.h:255
CHAR taskName[OS_TCB_NAME_LEN]
函数调用图:
这是这个函数的调用关系图:

◆ KillPgrp()

VOID KillPgrp ( UINT16  consoleId)

杀死进程组

在文件 console.c442 行定义.

443{
444 if ((consoleId > CONSOLE_NUM) || (consoleId <= 0)) {
445 return;
446 }
447 CONSOLE_CB *consoleCB = g_console[consoleId-1];
448 /* the default of consoleCB->pgrpId is -1, may not be set yet, avoid killing all processes */
449 if (consoleCB->pgrpId < 0) {
450 return;
451 }
452 (VOID)OsKillLock(consoleCB->pgrpId, SIGINT);//发送信号 SIGINT对应 键盘中断(ctrl + c)信号
453}
int OsKillLock(pid_t pid, int sig)
给发送信号过程加锁
Definition: los_signal.c:480
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleBufDeinit()

STATIC VOID OsConsoleBufDeinit ( CONSOLE_CB consoleCB)

控制台buf去初始化

在文件 console.c1218 行定义.

1219{
1220 CirBufSendCB *cirBufSendCB = consoleCB->cirBufSendCB;
1221
1222 consoleCB->cirBufSendCB = NULL;
1223 (VOID)LOS_EventWrite(&cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_EXIT);//写任务退出事件 ConsoleSendTask将会收到事件,退出死循环
1224}
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleBufInit()

STATIC UINT32 OsConsoleBufInit ( CONSOLE_CB consoleCB)

控制台缓存初始化,创建一个 发送任务

在文件 console.c1189 行定义.

1190{
1191 UINT32 ret;
1192 TSK_INIT_PARAM_S initParam = {0};
1193
1194 consoleCB->cirBufSendCB = ConsoleCirBufCreate();//创建控制台
1195 if (consoleCB->cirBufSendCB == NULL) {
1196 return LOS_NOK;
1197 }
1198
1199 initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ConsoleSendTask;//控制台发送任务入口函数
1200 initParam.usTaskPrio = SHELL_TASK_PRIORITY; //优先级9
1201 initParam.auwArgs[0] = (UINTPTR)consoleCB; //入口函数的参数
1202 initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; //16K
1203 initParam.pcName = (consoleCB->consoleID == CONSOLE_SERIAL) ? "SendToSer" : "SendToTelnet"; //控制台的两种方式
1204 initParam.uwResved = LOS_TASK_STATUS_DETACHED; //使用任务分离模式
1205
1206 ret = LOS_TaskCreate(&consoleCB->sendTaskID, &initParam);//创建task 并加入就绪队列,申请立即调度
1207 if (ret != LOS_OK) { //创建失败处理
1208 ConsoleCirBufDelete(consoleCB->cirBufSendCB);//释放循环buf
1209 consoleCB->cirBufSendCB = NULL;//置NULL
1210 return LOS_NOK;
1211 }//永久等待读取 CONSOLE_SEND_TASK_RUNNING 事件,CONSOLE_SEND_TASK_RUNNING 由 ConsoleSendTask 发出.
1212 (VOID)LOS_EventRead(&consoleCB->cirBufSendCB->sendEvent, CONSOLE_SEND_TASK_RUNNING,
1213 LOS_WAITMODE_OR | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
1214 // ... 读取到 CONSOLE_SEND_TASK_RUNNING 事件才会往下执行
1215 return LOS_OK;
1216}
STATIC CirBufSendCB * ConsoleCirBufCreate(VOID)
创建一个控制台循环buf
Definition: console.c:1144
STATIC UINT32 ConsoleSendTask(UINTPTR param)
控制台发送任务
Definition: console.c:1595
LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam)
创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务
Definition: los_task.c:718
VOID *(* TSK_ENTRY_FUNC)(UINTPTR param1, UINTPTR param2, UINTPTR param3, UINTPTR param4)
Define the type of a task entrance function.
Definition: los_task.h:480
UINT32 sendTaskID
创建任务通过事件接收数据, 见于OsConsoleBufInit
Definition: console.h:120
UINT16 usTaskPrio
Definition: los_task.h:505
UINTPTR auwArgs[4]
Definition: los_task.h:507
UINT32 uwStackSize
Definition: los_task.h:508
CHAR * pcName
Definition: los_task.h:509
TSK_ENTRY_FUNC pfnTaskEntry
Definition: los_task.h:504
UINT32 uwResved
Definition: los_task.h:513
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleCBDeinit()

STATIC VOID OsConsoleCBDeinit ( CONSOLE_CB consoleCB)

释放控制台描述符初始化时所占用的内核空间

在文件 console.c1246 行定义.

1247{
1248 (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB->name);//释放控制台名称占用的内核内存
1249 consoleCB->name = NULL;
1250 (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB);//释放控制台描述符所占用的内核内存
1251}
CHAR * name
名称 例如: /dev/console1
Definition: console.h:111
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleCBInit()

STATIC CONSOLE_CB * OsConsoleCBInit ( UINT32  consoleID)

控制台描述符初始化

在文件 console.c1226 行定义.

1227{
1228 CONSOLE_CB *consoleCB = (CONSOLE_CB *)LOS_MemAlloc((VOID *)m_aucSysMem0, sizeof(CONSOLE_CB));//内核空间分配控制台描述符
1229 if (consoleCB == NULL) {
1230 return NULL;
1231 }
1232 (VOID)memset_s(consoleCB, sizeof(CONSOLE_CB), 0, sizeof(CONSOLE_CB));//清0
1233
1234 consoleCB->consoleID = consoleID;//记录控制台ID
1235 consoleCB->pgrpId = -1;
1236 consoleCB->shellEntryId = SHELL_ENTRYID_INVALID; /* initialize shellEntryId to an invalid value *///将shellEntryId初始化为无效值
1237 consoleCB->name = LOS_MemAlloc((VOID *)m_aucSysMem0, CONSOLE_NAMELEN);//控制台名称 不能多于16个字符
1238 if (consoleCB->name == NULL) {
1239 PRINT_ERR("consoleCB->name malloc failed\n");
1240 (VOID)LOS_MemFree((VOID *)m_aucSysMem0, consoleCB);
1241 return NULL;
1242 }
1243 return consoleCB;
1244}
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleCreate()

STATIC CONSOLE_CB * OsConsoleCreate ( UINT32  consoleID,
const CHAR deviceName 
)

创建一个控制台,这个函数的goto语句贼多

在文件 console.c1253 行定义.

1254{
1255 INT32 ret;
1256 CONSOLE_CB *consoleCB = OsConsoleCBInit(consoleID);//初始化控制台
1257 if (consoleCB == NULL) {
1258 PRINT_ERR("console malloc error.\n");
1259 return NULL;
1260 }
1261
1262 ret = snprintf_s(consoleCB->name, CONSOLE_NAMELEN, CONSOLE_NAMELEN - 1,
1263 "%s%u", CONSOLE, consoleCB->consoleID);//通过printf方式得到name 例如: /dev/console1
1264 if (ret == -1) {
1265 PRINT_ERR("consoleCB->name snprintf_s failed\n");
1266 goto ERR_WITH_NAME;
1267 }
1268
1269 ret = (INT32)OsConsoleBufInit(consoleCB);//控制台buf初始化,创建 ConsoleSendTask 任务
1270 if (ret != LOS_OK) {
1271 PRINT_ERR("console OsConsoleBufInit error. %d\n", ret);
1272 goto ERR_WITH_NAME;
1273 }
1274
1275 ret = (INT32)LOS_SemCreate(1, &consoleCB->consoleSem);//创建控制台信号量
1276 if (ret != LOS_OK) {
1277 PRINT_ERR("creat sem for uart failed\n");
1278 goto ERR_WITH_BUF;
1279 }
1280
1281 ret = OsConsoleDevInit(consoleCB, deviceName);//控制台设备初始化,注意这步要在 OsConsoleFileInit 的前面.
1282 if (ret != LOS_OK) {//先注册驱动程序
1283 PRINT_ERR("console OsConsoleDevInit error. %d\n", ret);
1284 goto ERR_WITH_SEM;
1285 }
1286
1287 ret = OsConsoleFileInit(consoleCB); //为 /dev/console(n|1:2)分配fd(n)
1288 if (ret != LOS_OK) {
1289 PRINT_ERR("console OsConsoleFileInit error. %d\n", ret);
1290 goto ERR_WITH_DEV;
1291 }
1292
1293 OsConsoleTermiosInit(consoleCB, deviceName);//控制台行规程初始化
1294 return consoleCB;
1295
1296ERR_WITH_DEV:
1297 ret = (INT32)OsConsoleDevDeinit(consoleCB);//控制台设备注销
1298 if (ret != LOS_OK) {
1299 PRINT_ERR("OsConsoleDevDeinit failed!\n");
1300 }
1301ERR_WITH_SEM:
1302 (VOID)LOS_SemDelete(consoleCB->consoleSem);//控制台信号量删除
1303ERR_WITH_BUF:
1304 OsConsoleBufDeinit(consoleCB);//控制台buf取消初始化
1305ERR_WITH_NAME:
1306 OsConsoleCBDeinit(consoleCB);//控制块取消初始化
1307 return NULL;
1308}
STATIC UINT32 OsConsoleBufInit(CONSOLE_CB *consoleCB)
控制台缓存初始化,创建一个 发送任务
Definition: console.c:1189
STATIC VOID OsConsoleCBDeinit(CONSOLE_CB *consoleCB)
释放控制台描述符初始化时所占用的内核空间
Definition: console.c:1246
STATIC VOID OsConsoleBufDeinit(CONSOLE_CB *consoleCB)
控制台buf去初始化
Definition: console.c:1218
STATIC VOID OsConsoleTermiosInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口, 通过设置termios类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。
Definition: console.c:1008
STATIC CONSOLE_CB * OsConsoleCBInit(UINT32 consoleID)
控制台描述符初始化
Definition: console.c:1226
STATIC INT32 OsConsoleFileInit(CONSOLE_CB *consoleCB)
控制台文件实例初始化
Definition: console.c:1038
STATIC INT32 OsConsoleDevInit(CONSOLE_CB *consoleCB, const CHAR *deviceName)
Definition: console.c:1068
STATIC UINT32 OsConsoleDevDeinit(const CONSOLE_CB *consoleCB)
注销控制台设备
Definition: console.c:1138
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemCreate(UINT16 count, UINT32 *semHandle)
对外接口 创建信号量
Definition: los_sem.c:177
LITE_OS_SEC_TEXT_INIT UINT32 LOS_SemDelete(UINT32 semHandle)
对外接口 删除指定的信号量,参数就是 semID
Definition: los_sem.c:187
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleDelete()

STATIC UINT32 OsConsoleDelete ( CONSOLE_CB consoleCB)

删除控制台

在文件 console.c1310 行定义.

1311{
1312 UINT32 ret;
1313
1314 (VOID)files_close(consoleCB->fd);//回收系统文件句柄
1315 ret = OsConsoleDevDeinit(consoleCB);//注销驱动程序
1316 if (ret != LOS_OK) {
1317 PRINT_ERR("OsConsoleDevDeinit failed!\n");
1318 }
1319 OsConsoleBufDeinit((CONSOLE_CB *)consoleCB);//回收环形缓存区
1320 (VOID)LOS_SemDelete(consoleCB->consoleSem);//删除信号量
1321 (VOID)LOS_MemFree(m_aucSysMem0, consoleCB->name);//回收控制台名称,此名称占用内核内存
1322 consoleCB->name = NULL;
1323 (VOID)LOS_MemFree(m_aucSysMem0, consoleCB);//回收控制块本身占用的内存
1324
1325 return ret;
1326}
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleDevDeinit()

STATIC UINT32 OsConsoleDevDeinit ( const CONSOLE_CB consoleCB)

注销控制台设备

在文件 console.c1138 行定义.

1139{
1140 return unregister_driver(consoleCB->name);//注销驱动
1141}
这是这个函数的调用关系图:

◆ OsConsoleDevInit()

STATIC INT32 OsConsoleDevInit ( CONSOLE_CB consoleCB,
const CHAR deviceName 
)

在文件 console.c1068 行定义.

1069{
1070 INT32 ret;
1071 struct file *filep = NULL;
1072 struct Vnode *vnode = NULL;
1073 struct file_operations_vfs *devOps = NULL;
1074
1075 /* allocate memory for filep,in order to unchange the value of filep */
1076 filep = (struct file *)LOS_MemAlloc(m_aucSysMem0, sizeof(struct file));
1077 if (filep == NULL) {
1078 ret = ENOMEM;
1079 goto ERROUT;
1080 }
1081
1082 VnodeHold();
1083 ret = VnodeLookup(deviceName, &vnode, V_DUMMY); //找到对应 vnode节点
1084 VnodeDrop(); // not correct, but can't fix perfectly here
1085 if (ret != LOS_OK) {
1086 ret = EACCES;
1087 PRINTK("!! can not find %s\n", consoleCB->name);
1088 goto ERROUT;
1089 }
1090
1091 consoleCB->devVnode = vnode;//关联vnode节点
1092
1093 /*
1094 * initialize the console filep which is associated with /dev/console,
1095 * assign the uart0 inode of /dev/ttyS0 to console inod of /dev/console,
1096 * then we can operate console's filep as if we operate uart0 filep of
1097 * /dev/ttyS0.
1098 */
1099 /*
1100 初始化与/dev/console关联的console filep,将/dev/ttyS0的uart0 inode赋给
1101 /dev/console的console inod,就可以像操作/dev/ttyS0的uart0 filep一样操作控制台的filep
1102 */
1103 (VOID)memset_s(filep, sizeof(struct file), 0, sizeof(struct file));
1104 filep->f_oflags = O_RDWR; //读写模式
1105 filep->f_pos = 0; //偏移位置,默认为0
1106 filep->f_vnode = vnode; //节点关联
1107 filep->f_path = NULL; //
1108 filep->f_priv = NULL; //
1109 /*
1110 * Use filep to connect console and uart, we can find uart driver function throught filep.
1111 * now we can operate /dev/console to operate /dev/ttyS0 through filep.
1112 */
1113 //使用filep连接控制台和uart,通过它可以找到uart驱动函数, 可以通过filep操作/dev/console
1114 devOps = (struct file_operations_vfs *)((struct drv_data*)vnode->data)->ops;//获取默认驱动程序
1115 if (devOps != NULL && devOps->open != NULL) {
1116 (VOID)devOps->open(filep);
1117 } else {
1118 ret = ENOSYS;
1119 goto ERROUT;
1120 }
1121
1122 ret = register_driver(consoleCB->name, &g_consoleDevOps, DEFFILEMODE, filep);//注册控制台设备驱动程序
1123 if (ret != LOS_OK) {
1124 goto ERROUT;
1125 }
1126
1127 return LOS_OK;
1128
1129ERROUT:
1130 if (filep) {
1131 (VOID)LOS_MemFree(m_aucSysMem0, filep);
1132 }
1133
1134 set_errno(ret);
1135 return LOS_NOK;
1136}
STATIC const struct file_operations_vfs g_consoleDevOps
Definition: console.c:988
struct Vnode * devVnode
索引节点
Definition: console.h:110
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
void * data
Definition: vnode.h:176
loff_t f_pos
int f_oflags
int VnodeDrop(void)
归还锁
Definition: vnode.c:292
int VnodeHold(void)
拿锁,封装互斥量
Definition: vnode.c:283
int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
通过路径查询vnode节点
Definition: vnode.c:491
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleFileInit()

STATIC INT32 OsConsoleFileInit ( CONSOLE_CB consoleCB)

控制台文件实例初始化

在文件 console.c1038 行定义.

1039{
1040 INT32 ret;
1041 struct Vnode *vnode = NULL;
1042 struct file *filep = NULL;
1043
1044 VnodeHold();
1045 ret = VnodeLookup(consoleCB->name, &vnode, 0);
1046 if (ret != LOS_OK) {
1047 ret = EACCES;
1048 goto ERROUT;
1049 }
1050
1051 filep = files_allocate(vnode, O_RDWR, 0, consoleCB, FILE_START_FD);//分配FD给了控制台
1052 if (filep == NULL) {
1053 ret = EMFILE;
1054 goto ERROUT;
1055 }
1056 filep->ops = (struct file_operations_vfs *)((struct drv_data *)vnode->data)->ops;//关联驱动程序
1057 consoleCB->fd = filep->fd;
1058
1059ERROUT:
1060 VnodeDrop();
1061 return ret;
1062}
函数调用图:
这是这个函数的调用关系图:

◆ OsConsoleFullpathToID()

STATIC INT32 OsConsoleFullpathToID ( const CHAR fullpath)

通过路径找到控制台ID

在文件 console.c276 行定义.

277{
278#define CONSOLE_SERIAL_1 "/dev/console1"
279#define CONSOLE_TELNET_2 "/dev/console2"
280
281 size_t len;
282
283 if (fullpath == NULL) {
284 return -1;
285 }
286
287 len = strlen(fullpath);
288 if ((len == strlen(CONSOLE_SERIAL_1)) &&
289 (!strncmp(fullpath, CONSOLE_SERIAL_1, strlen(CONSOLE_SERIAL_1)))) {
290 return CONSOLE_SERIAL;
291 }
292#ifdef LOSCFG_NET_TELNET
293 else if ((len == strlen(CONSOLE_TELNET_2)) &&
294 (!strncmp(fullpath, CONSOLE_TELNET_2, strlen(CONSOLE_TELNET_2)))) {
295 return CONSOLE_TELNET;
296 }
297#endif
298 return -1;
299}
这是这个函数的调用关系图:

◆ OsConsoleTermiosInit()

STATIC VOID OsConsoleTermiosInit ( CONSOLE_CB consoleCB,
const CHAR deviceName 
)

termios 结构是在POSIX规范中定义的标准接口,它类似于系统V中的termio接口, 通过设置termios类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。

参数
consoleCB
deviceName
返回
STATIC

在文件 console.c1008 行定义.

1009{
1010 struct termios consoleTermios = {0};
1011//c_cc[VINTR] 默认对应的控制符是^C,作用是清空输入和输出队列的数据并且向tty设备的前台进程组中的
1012//每一个程序发送一个SIGINT信号,对SIGINT信号没有定义处理程序的进程会马上退出。
1013 if ((deviceName != NULL) &&
1014 (strlen(deviceName) == strlen(SERIAL)) &&
1015 (!strncmp(deviceName, SERIAL, strlen(SERIAL)))) {
1016 consoleCB->isNonBlock = SetSerialBlock(consoleCB);
1017
1018 /* set console to have a buffer for user */
1019 (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
1020 consoleTermios.c_lflag |= ICANON | ECHO;//控制模式标志 ICANON:使用标准输入模式 ECHO:显示输入字符
1021 consoleTermios.c_cc[VINTR] = 3; /* /003 for ^C */ //控制字符
1022 (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
1023 }
1024#ifdef LOSCFG_NET_TELNET
1025 else if ((deviceName != NULL) &&
1026 (strlen(deviceName) == strlen(TELNET)) &&
1027 (!strncmp(deviceName, TELNET, strlen(TELNET)))) {
1028 consoleCB->isNonBlock = SetTelnetBlock(consoleCB);
1029 /* set console to have a buffer for user */
1030 (VOID)ConsoleTcGetAttr(consoleCB->fd, &consoleTermios);
1031 consoleTermios.c_lflag |= ICANON | ECHO;//控制模式标志 ICANON:使用标准输入模式 ECHO:显示输入字符
1032 consoleTermios.c_cc[VINTR] = 3; /* /003 for ^C */ //控制字符
1033 (VOID)ConsoleTcSetAttr(consoleCB->fd, 0, &consoleTermios);
1034 }
1035#endif
1036}
BOOL SetSerialBlock(const CONSOLE_CB *consoleCB)
锁方式设置串口
Definition: console.c:1479
INT32 ConsoleTcGetAttr(INT32 fd, struct termios *termios)
获取控制台 模式值
Definition: console.c:122
BOOL SetTelnetBlock(const CONSOLE_CB *consoleCB)
锁方式设置远程登录
Definition: console.c:1499
函数调用图:
这是这个函数的调用关系图:

◆ OsGetConsoleByDevice()

STATIC CONSOLE_CB * OsGetConsoleByDevice ( const CHAR deviceName)

在文件 console.c236 行定义.

237{
238 INT32 ret;
239 struct Vnode *vnode = NULL;
240
241 VnodeHold();
242 ret = VnodeLookup(deviceName, &vnode, 0);
243 VnodeDrop();
244 if (ret < 0) {
245 set_errno(EACCES);
246 return NULL;
247 }
248
249 if (g_console[CONSOLE_SERIAL - 1]->devVnode == vnode) {
250 return g_console[CONSOLE_SERIAL - 1];
251 } else if (g_console[CONSOLE_TELNET - 1]->devVnode == vnode) {
252 return g_console[CONSOLE_TELNET - 1];
253 } else {
254 set_errno(ENOENT);
255 return NULL;
256 }
257}
函数调用图:
这是这个函数的调用关系图:

◆ OsGetConsoleByID()

CONSOLE_CB * OsGetConsoleByID ( INT32  consoleID)

获取参数控制台ID 获取对应的控制台控制块(描述符)

在文件 console.c1546 行定义.

1547{
1548 if (consoleID != CONSOLE_TELNET) {//只允许 1,2存在,> 3 时统统变成1
1549 consoleID = CONSOLE_SERIAL;
1550 }
1551 return g_console[consoleID - 1];
1552}
这是这个函数的调用关系图:

◆ OsGetConsoleByTaskID()

CONSOLE_CB * OsGetConsoleByTaskID ( UINT32  taskID)

获取参数任务的控制台控制块(描述符)

在文件 console.c1554 行定义.

1555{
1556 INT32 consoleID = g_taskConsoleIDArray[taskID];
1557
1558 return OsGetConsoleByID(consoleID);
1559}
CONSOLE_CB * OsGetConsoleByID(INT32 consoleID)
获取参数控制台ID 获取对应的控制台控制块(描述符)
Definition: console.c:1546
函数调用图:
这是这个函数的调用关系图:

◆ OsGetConsoleID()

STATIC INT32 OsGetConsoleID ( const CHAR deviceName)

获取控制台ID,(/dev/console1 = SERIAL, /dev/console2 = telnet)

在文件 console.c259 行定义.

260{
261 if ((deviceName != NULL) &&
262 (strlen(deviceName) == strlen(SERIAL)) &&
263 (!strncmp(deviceName, SERIAL, strlen(SERIAL)))) {
264 return CONSOLE_SERIAL;//1 串口
265 }
266#ifdef LOSCFG_NET_TELNET
267 else if ((deviceName != NULL) &&
268 (strlen(deviceName) == strlen(TELNET)) &&
269 (!strncmp(deviceName, TELNET, strlen(TELNET)))) {
270 return CONSOLE_TELNET;//2 远程登录
271 }
272#endif
273 return -1;
274}
这是这个函数的调用关系图:

◆ OsSetConsoleID()

VOID OsSetConsoleID ( UINT32  newTaskID,
UINT32  curTaskID 
)

设置控制台ID

在文件 console.c1561 行定义.

1562{
1563 if ((newTaskID >= LOSCFG_BASE_CORE_TSK_LIMIT) || (curTaskID >= LOSCFG_BASE_CORE_TSK_LIMIT)) {
1564 return;
1565 }
1566
1567 g_taskConsoleIDArray[newTaskID] = g_taskConsoleIDArray[curTaskID];
1568}

◆ OsWaitConsoleSendTaskPend()

VOID OsWaitConsoleSendTaskPend ( UINT32  taskID)

在文件 console.c1633 行定义.

1634{
1635 UINT32 i;
1636 CONSOLE_CB *console = NULL;
1637 LosTaskCB *taskCB = NULL;
1638 INT32 waitTime = 3000; /* 3000: 3 seconds */
1639
1640 for (i = 0; i < CONSOLE_NUM; i++) {//轮询控制台
1641 console = g_console[i];
1642 if (console == NULL) {
1643 continue;
1644 }
1645
1646 if (OS_TID_CHECK_INVALID(console->sendTaskID)) {
1647 continue;
1648 }
1649
1650 taskCB = OS_TCB_FROM_TID(console->sendTaskID);
1651 while ((waitTime > 0) && (taskCB->taskEvent == NULL) && (taskID != console->sendTaskID)) {
1652 LOS_Mdelay(1); /* 1: wait console task pend */ //等待控制台任务挂起/待办
1653 --waitTime;
1654 }
1655 }
1656}
LITE_OS_SEC_TEXT_MINOR VOID LOS_Mdelay(UINT32 msecs)
以ms为单位的忙等,但可以被优先级更高的任务抢占
Definition: los_hw_tick.c:73
VOID * taskEvent
函数调用图:
这是这个函数的调用关系图:

◆ OsWakeConsoleSendTask()

VOID OsWakeConsoleSendTask ( VOID  )

唤醒控制台发送任务

在文件 console.c1658 行定义.

1659{
1660 UINT32 i;
1661 CONSOLE_CB *console = NULL;
1662
1663 for (i = 0; i < CONSOLE_NUM; i++) {//循环控制台数量,只有2个
1664 console = g_console[i];
1665 if (console == NULL) {
1666 continue;
1667 }
1668
1669 if (console->cirBufSendCB != NULL) {//循环缓存描述符
1670 (VOID)LOS_EventWrite(&console->cirBufSendCB->sendEvent, CONSOLE_CIRBUF_EVENT);//写循环缓存区buf事件
1671 }
1672 }
1673}
函数调用图:
这是这个函数的调用关系图:

◆ SetSerialBlock()

BOOL SetSerialBlock ( const CONSOLE_CB consoleCB)

锁方式设置串口

在文件 console.c1479 行定义.

1480{
1481 if (consoleCB == NULL) {
1482 PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1483 return TRUE;
1484 }
1485 return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_SERIAL, CONSOLE_RD_BLOCK) != 0;
1486}
这是这个函数的调用关系图:

◆ SetSerialNonBlock()

BOOL SetSerialNonBlock ( const CONSOLE_CB consoleCB)

无锁方式设置串口

在文件 console.c1469 行定义.

1470{
1471 if (consoleCB == NULL) {
1472 PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1473 return FALSE;
1474 }
1475 return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_SERIAL, CONSOLE_RD_NONBLOCK) == 0;
1476}

◆ SetTelnetBlock()

BOOL SetTelnetBlock ( const CONSOLE_CB consoleCB)

锁方式设置远程登录

在文件 console.c1499 行定义.

1500{
1501 if (consoleCB == NULL) {
1502 PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1503 return TRUE;
1504 }
1505 return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_TELNET, CONSOLE_RD_BLOCK) != 0;
1506}
这是这个函数的调用关系图:

◆ SetTelnetNonBlock()

BOOL SetTelnetNonBlock ( const CONSOLE_CB consoleCB)

无锁方式设置远程登录

在文件 console.c1489 行定义.

1490{
1491 if (consoleCB == NULL) {
1492 PRINT_ERR("%s: Input parameter is illegal\n", __FUNCTION__);
1493 return FALSE;
1494 }
1495 return ioctl(consoleCB->fd, CONSOLE_CMD_RD_BLOCK_TELNET, CONSOLE_RD_NONBLOCK) == 0;
1496}

◆ SPIN_LOCK_INIT() [1/2]

STATIC SPIN_LOCK_INIT ( g_consoleSpin  )

初始化控制台自旋锁

◆ SPIN_LOCK_INIT() [2/2]

STATIC SPIN_LOCK_INIT ( g_consoleWriteSpinLock  )

◆ StoreReadChar()

STATIC VOID StoreReadChar ( CONSOLE_CB consoleCB,
char  ch,
INT32  readcount 
)

存储读取的字符

在文件 console.c428 行定义.

429{ //读取字符
430 if ((readcount == EACH_CHAR) && (consoleCB->fifoIn <= (CONSOLE_FIFO_SIZE - 3))) {
431 if (ch == '\b') {
432 if (!ConsoleFifoEmpty(consoleCB)) {
433 consoleCB->fifo[--consoleCB->fifoIn] = '\0';
434 }
435 } else {
436 consoleCB->fifo[consoleCB->fifoIn] = (UINT8)ch;//将字符读入缓冲区
437 consoleCB->fifoIn++;
438 }
439 }
440}
unsigned char UINT8
Definition: los_typedef.h:55
函数调用图:
这是这个函数的调用关系图:

◆ system_console_deinit()

INT32 system_console_deinit ( const CHAR deviceName)

控制台结束前的处理 和 system_console_init成对出现,像控制台的析构函数

在文件 console.c1375 行定义.

1376{
1377 UINT32 ret;
1378 CONSOLE_CB *consoleCB = NULL;
1379 UINT32 taskIdx;
1380 LosTaskCB *taskCB = NULL;
1381 UINT32 intSave;
1382
1383 consoleCB = OsGetConsoleByDevice(deviceName);//通过设备名称获取控制台描述符
1384 if (consoleCB == NULL) {
1385 return VFS_ERROR;
1386 }
1387
1388#ifdef LOSCFG_SHELL
1389 (VOID)OsShellDeinit((INT32)consoleCB->consoleID);//shell结束前的处理,shell的析构函数
1390#endif
1391
1392 LOS_SpinLockSave(&g_consoleSpin, &intSave);
1393 /* Redirect all tasks to serial as telnet was unavailable after deinitializing */
1394 //在远程登陆去初始化后变成无效时,将所有任务的控制台重定向到串口方式。
1395 for (taskIdx = 0; taskIdx < g_taskMaxNum; taskIdx++) {//这里是对所有的任务控制台方式设为串口化
1396 taskCB = ((LosTaskCB *)g_taskCBArray) + taskIdx;
1397 if (OsTaskIsUnused(taskCB)) {//任务还没被使用过
1398 continue;//继续
1399 } else {
1400 g_taskConsoleIDArray[taskCB->taskID] = CONSOLE_SERIAL;//任务对于的控制台变成串口方式
1401 }
1402 }
1403 g_console[consoleCB->consoleID - 1] = NULL;
1404 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1405
1406 ret = OsConsoleDelete(consoleCB);//删除控制台
1407 if (ret != LOS_OK) {
1408 PRINT_ERR("%s, Failed to system_console_deinit\n", __FUNCTION__);
1409 return VFS_ERROR;
1410 }
1411
1412 return ENOERR;
1413}
int OsShellDeinit(ShellCB *shellCB)
STATIC CONSOLE_CB * OsGetConsoleByDevice(const CHAR *deviceName)
Definition: console.c:236
STATIC UINT32 OsConsoleDelete(CONSOLE_CB *consoleCB)
删除控制台
Definition: console.c:1310
LITE_OS_SEC_BSS UINT32 g_taskMaxNum
任务最大数量 默认128个
Definition: los_task.c:150
LITE_OS_SEC_BSS LosTaskCB * g_taskCBArray
外部变量 任务池 默认128个
Definition: los_task.c:147
函数调用图:
这是这个函数的调用关系图:

◆ system_console_init()

INT32 system_console_init ( const CHAR deviceName)

初始化系统控制台并返回 stdinfd stdoutfd stderrfd ,和system_console_deinit成对出现,像控制台的构造函数

https://man7.org/linux/man-pages/man3/tcflow.3.html termios 是在POSIX规范中定义的标准接口,表示终端设备,包括虚拟终端、串口等。串口通过termios进行配置。 struct termios { unsigned short c_iflag; // 输入模式标志 unsigned short c_oflag; // 输出模式标志 unsigned short c_cflag; // 控制模式标志 unsigned short c_lflag; // 本地模式标志 例如: 设置非规范模式 tios.c_lflag = ~(ICANON | ECHO | ECHOE | ISIG); unsigned char c_line; // 线路规程 unsigned char c_cc[NCC]; // 控制特性 speed_t c_ispeed; // 输入速度 speed_t c_ospeed; // 输出速度 } 终端有三种工作模式: 规范模式(canonical mode)、 非规范模式(non-canonical mode) 原始模式(raw mode)。 https://www.jianshu.com/p/fe5812469801 https://blog.csdn.net/wumenglu1018/article/details/53098794

在文件 console.c1329 行定义.

1330{
1331#ifdef LOSCFG_SHELL
1332 UINT32 ret;
1333#endif
1334 INT32 consoleID;
1335 UINT32 intSave;
1336 CONSOLE_CB *consoleCB = NULL;
1337
1338 consoleID = OsGetConsoleID(deviceName);//获取控制台ID 返回[ CONSOLE_SERIAL(1) | CONSOLE_TELNET(2) | -1 ]三种结果
1339 if (consoleID == -1) {
1340 PRINT_ERR("device is full.\n");
1341 return VFS_ERROR;
1342 }
1343
1344 consoleCB = OsConsoleCreate((UINT32)consoleID, deviceName);//创建一个控制台
1345 if (consoleCB == NULL) {
1346 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1347 return VFS_ERROR;
1348 }
1349
1350 LOS_SpinLockSave(&g_consoleSpin, &intSave);
1351 g_console[consoleID - 1] = consoleCB;//全局变量, g_console最大值只有2 ,所有任务共用控制台.
1352 if (OsCurrTaskGet() != NULL) {//当前task
1353 g_taskConsoleIDArray[OsCurrTaskGet()->taskID] = (UINT8)consoleID;//任务绑定控制台ID
1354 }
1355 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1356
1357#ifdef LOSCFG_SHELL //shell支持
1358 ret = OsShellInit(consoleID);//初始化shell
1359 if (ret != LOS_OK) {//初始化shell失败
1360 PRINT_ERR("%s, %d\n", __FUNCTION__, __LINE__);
1361 LOS_SpinLockSave(&g_consoleSpin, &intSave);
1362 (VOID)OsConsoleDelete(consoleCB);//删除控制台
1363 g_console[consoleID - 1] = NULL;
1364 if (OsCurrTaskGet() != NULL) {
1365 g_taskConsoleIDArray[OsCurrTaskGet()->taskID] = 0;//表示当前任务还没有控制台。
1366 }
1367 LOS_SpinUnlockRestore(&g_consoleSpin, intSave);
1368 return VFS_ERROR;
1369 }
1370#endif
1371
1372 return ENOERR;
1373}
unsigned int OsShellInit(void)
STATIC INT32 OsGetConsoleID(const CHAR *deviceName)
获取控制台ID,(/dev/console1 = SERIAL, /dev/console2 = telnet)
Definition: console.c:259
STATIC CONSOLE_CB * OsConsoleCreate(UINT32 consoleID, const CHAR *deviceName)
创建一个控制台,这个函数的goto语句贼多
Definition: console.c:1253
函数调用图:
这是这个函数的调用关系图:

◆ UserEndOfRead()

STATIC INLINE VOID UserEndOfRead ( CONSOLE_CB consoleCB,
struct file filep,
const struct file_operations_vfs *  fops 
)

向控制台buf中写入结束字符

在文件 console.c353 行定义.

355{
356 CHAR ch;
357 if (consoleCB->consoleTermios.c_lflag & ECHO) {
358 ch = '\r';
359 (VOID)fops->write(filep, &ch, 1);
360 }
361 consoleCB->fifo[consoleCB->fifoIn++] = '\n';
362 consoleCB->fifo[consoleCB->fifoIn] = '\0';
363 consoleCB->currentLen = consoleCB->fifoIn;
364}
这是这个函数的调用关系图:

◆ UserFilepRead()

STATIC INT32 UserFilepRead ( CONSOLE_CB consoleCB,
struct file filep,
const struct file_operations_vfs *  fops,
CHAR buffer,
size_t  bufLen 
)

使用参数buffer将控制台的buf接走

在规范模式下,输入数据基于行进行处理。 在用户输入一个行结束符(回车符、EOF等)之前,系统调用read()读不到用户输入的任何字符。 除了EOF之外的行结束符(回车符等),与普通字符一样会被read()读到缓冲区中。 在规范模式中,可以进行行编辑,而且一次调用read()最多只能读取一行数据。 如果read()请求读取的数据字节少于当前行可读取的字节,则read()只读取被请求的字节数,剩下的字节下次再读。

在文件 console.c455 行定义.

457{
458 INT32 ret;
459 INT32 needreturn = LOS_NOK;
460 CHAR ch;
461 INT32 lastTokenType = STAT_NORMAL_KEY;
462
463 if (fops->read == NULL) {
464 return -EFAULT;
465 }
466
467 /* Non-ICANON mode | 非规范模式 所有的输入即时有效,用户不需要另外输入行结束符,不能进行行编辑*/
468 if ((consoleCB->consoleTermios.c_lflag & ICANON) == 0) {
469 ret = fops->read(filep, buffer, bufLen);
470 return (ret < 0) ? -EPERM : ret;
471 }
472 /**
473 在规范模式下,输入数据基于行进行处理。
474 在用户输入一个行结束符(回车符、EOF等)之前,系统调用read()读不到用户输入的任何字符。
475 除了EOF之外的行结束符(回车符等),与普通字符一样会被read()读到缓冲区中。
476 在规范模式中,可以进行行编辑,而且一次调用read()最多只能读取一行数据。
477 如果read()请求读取的数据字节少于当前行可读取的字节,则read()只读取被请求的字节数,剩下的字节下次再读。
478 */
479 /* ICANON mode: store data to console buffer, read data and stored data into console fifo */
480 if (consoleCB->currentLen == 0) {//如果没有数据
481 while (1) {//存储数据到控制台buf中
482 ret = fops->read(filep, &ch, EACH_CHAR);//一个个字符读
483 if (ret <= 0) {
484 return ret;
485 }
486
487 if (IsNeedContinue(consoleCB, ch, &lastTokenType))//是否继续读
488 continue;
489
490 switch (ch) {
491 case '\r':
492 ch = '\n';//回车换行
493 case '\n':
494 EchoToTerminal(consoleCB, filep, fops, ch);//输出到终端
495 UserEndOfRead(consoleCB, filep, fops);//给控制台buf加上结束字符
496 ret = ConsoleReadFifo(buffer, consoleCB, bufLen);//读取控制台buf的信息到参数buffer中
497 needreturn = LOS_OK;//直接返回
498 break;
499 case '\b':
500 default:
501 EchoToTerminal(consoleCB, filep, fops, ch);//输出到终端
502 StoreReadChar(consoleCB, ch, ret);//将字符保存到控制台的buf中
503 break;
504 }
505
506 if (needreturn == LOS_OK)
507 break;
508 }
509 } else {//如果数据准备好了,立即返回
510 /* if data is already in console fifo, we returen them immediately */
511 ret = ConsoleReadFifo(buffer, consoleCB, bufLen);//读取控制台buf的信息到参数buffer中
512 }
513
514 return ret;
515}
STATIC VOID StoreReadChar(CONSOLE_CB *consoleCB, char ch, INT32 readcount)
存储读取的字符
Definition: console.c:428
STATIC VOID EchoToTerminal(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops, char ch)
输出到终端
Definition: console.c:417
STATIC INT32 IsNeedContinue(CONSOLE_CB *consoleCB, char ch, INT32 *lastTokenType)
是否需要继续
Definition: console.c:407
STATIC INT32 ConsoleReadFifo(CHAR *buffer, CONSOLE_CB *console, size_t bufLen)
读取
Definition: console.c:318
STATIC INLINE VOID UserEndOfRead(CONSOLE_CB *consoleCB, struct file *filep, const struct file_operations_vfs *fops)
向控制台buf中写入结束字符
Definition: console.c:353
函数调用图:
这是这个函数的调用关系图:

◆ UserShellCheckUDRL()

STATIC INT32 UserShellCheckUDRL ( const CHAR  ch,
INT32 lastTokenType 
)

用户shell检查上下左右键

在文件 console.c372 行定义.

373{
374 INT32 ret = LOS_OK;
375 if (ch == 0x1b) { /* 0x1b: ESC */
376 *lastTokenType = STAT_ESC_KEY;// vt 的控制字符
377 return ret;
378 } else if (ch == 0x5b) { /* 0x5b: first Key combination */
379 if (*lastTokenType == STAT_ESC_KEY) { //遇到 <ESC>[
380 *lastTokenType = STAT_MULTI_KEY;
381 return ret;
382 }
383 } else if (ch == 0x41) { /* up */
384 if (*lastTokenType == STAT_MULTI_KEY) {
385 *lastTokenType = STAT_NORMAL_KEY;
386 return ret;
387 }
388 } else if (ch == 0x42) { /* down */
389 if (*lastTokenType == STAT_MULTI_KEY) {
390 *lastTokenType = STAT_NORMAL_KEY;
391 return ret;
392 }
393 } else if (ch == 0x43) { /* right */
394 if (*lastTokenType == STAT_MULTI_KEY) {
395 *lastTokenType = STAT_NORMAL_KEY;
396 return ret;
397 }
398 } else if (ch == 0x44) { /* left */
399 if (*lastTokenType == STAT_MULTI_KEY) {
400 *lastTokenType = STAT_NORMAL_KEY;
401 return ret;
402 }
403 }
404 return LOS_NOK;
405}
这是这个函数的调用关系图:

◆ WriteToTerminal()

STATIC ssize_t WriteToTerminal ( const CONSOLE_CB consoleCB,
const CHAR buffer,
size_t  bufLen 
)

将buf内容写到终端设备

在文件 console.c1570 行定义.

1571{
1572 INT32 ret, fd;
1573 INT32 cnt = 0;
1574 struct file *privFilep = NULL;
1575 struct file *filep = NULL;
1576 const struct file_operations_vfs *fileOps = NULL;
1577
1578 fd = consoleCB->fd;//获取文件描述符
1579 ret = fs_getfilep(fd, &filep);//获取文件指针
1580 ret = GetFilepOps(filep, &privFilep, &fileOps);//获取终端设备私有操作方法
1581
1582 if ((fileOps == NULL) || (fileOps->write == NULL)) {
1583 ret = EFAULT;
1584 goto ERROUT;
1585 }
1586 (VOID)fileOps->write(privFilep, buffer, bufLen);//写入终端设备,在终端设备上呈现出来
1587
1588 return cnt;
1589
1590ERROUT:
1591 set_errno(ret);
1592 return VFS_ERROR;
1593}
函数调用图:
这是这个函数的调用关系图:

变量说明

◆ g_console

CONSOLE_CB* g_console[CONSOLE_NUM]

控制台全局变量,控制台是共用的, 默认为 2个

在文件 console.c80 行定义.

◆ g_consoleDevOps

STATIC const struct file_operations_vfs g_consoleDevOps
初始值:
= {
.open = ConsoleOpen,
.close = ConsoleClose,
.read = ConsoleRead,
.write = ConsoleWrite,
.seek = NULL,
.ioctl = ConsoleIoctl,
.mmap = NULL,
#ifndef CONFIG_DISABLE_POLL
.poll = ConsolePoll,
#endif
}
STATIC ssize_t ConsoleRead(struct file *filep, CHAR *buffer, size_t bufLen)
任务从控制台读数据,例如 Shell Entry 任务会从此读数据
Definition: console.c:663
STATIC ssize_t ConsoleWrite(struct file *filep, const CHAR *buffer, size_t bufLen)
用户任务写数据到控制台
Definition: console.c:767
STATIC INT32 ConsoleOpen(struct file *filep)
对 file_operations_vfs->open 的实现函数,也就是说这是 打开控制台的实体函数.
Definition: console.c:587
STATIC INT32 ConsoleIoctl(struct file *filep, INT32 cmd, unsigned long arg)
Definition: console.c:887
STATIC INT32 ConsoleClose(struct file *filep)
关闭控制台
Definition: console.c:618
STATIC INT32 ConsolePoll(struct file *filep, poll_table *fds)
Definition: console.c:963

console device driver function structure | 控制台设备驱动程序,对统一的vfs接口的实现

在文件 console.c988 行定义.

◆ g_taskConsoleIDArray

STATIC UINT8 g_taskConsoleIDArray[LOSCFG_BASE_CORE_TSK_LIMIT]

task 控制台ID池,同步task数量,理论上每个task都可以有一个自己的控制台

在文件 console.c68 行定义.

◆ g_uart_fputc_en

UINT32 g_uart_fputc_en
extern