那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用系統(tǒng)IO和標(biāo)準(zhǔn)IO的基本原理

CHANBAEK ? 來(lái)源:非典型技術(shù)宅 ? 作者:非典型技術(shù)宅 ? 2023-11-24 09:48 ? 次閱讀

系統(tǒng) IO 和標(biāo)準(zhǔn) IO

系統(tǒng) IO 一般指的是 Linux/Unix 系統(tǒng)調(diào)用中關(guān)于 I/O 操作的統(tǒng)稱(chēng),其中包括 open、read、write、close 等操作。

與系統(tǒng) IO 對(duì)應(yīng)還有標(biāo)準(zhǔn) IO,標(biāo)準(zhǔn) IO 是 ISO 標(biāo)準(zhǔn)中 C 語(yǔ)言標(biāo)準(zhǔn)定義的 IO 訪問(wèn)接口,例如 fprintf/fgets 等 C 語(yǔ)言標(biāo)準(zhǔn)中定義的文件訪問(wèn)接口。

在 Linux 系統(tǒng)中 open/read/write 等函數(shù)的底層實(shí)現(xiàn)是通過(guò)系統(tǒng)調(diào)用訪問(wèn)的,在 STM32 的裸機(jī)中沒(méi)有操作系統(tǒng),更沒(méi)有這些系統(tǒng)調(diào)用。

但是我們可以用一種其他的方式去實(shí)現(xiàn)這些系統(tǒng) IO,而不需要操作系統(tǒng)。

半主機(jī)模式重寫(xiě)文件訪問(wèn)接口

這個(gè)方法其實(shí)就是利用半主機(jī)模式,去重寫(xiě)系統(tǒng)庫(kù)中關(guān)于半主機(jī)接口中關(guān)于文件訪問(wèn)接口的底層 "弱定義"

這個(gè)聽(tīng)上去好像挺陌生的,其實(shí)很多人都使用過(guò),就是最簡(jiǎn)單的 printf 重定向。

在 GCC 重定向 printf 到串口使用了如下代碼:

int _write(int fd, char * ptr, int len)
{
  HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
  return len;
}

這個(gè)就是在半主機(jī)模式下重寫(xiě)了 write 函數(shù)的底層接口,當(dāng)系統(tǒng)調(diào)用 printf 函數(shù)時(shí)最終會(huì)調(diào)到 _write 函數(shù)向串口寫(xiě)入數(shù)據(jù)。

ARM 關(guān)于主機(jī)模式的文檔 中,Direct semihosting C library function dependencies 一節(jié)提供了可重寫(xiě)的系統(tǒng) IO 的底層函數(shù)。

圖片

通過(guò)重寫(xiě)上述列表中的函數(shù),即可通過(guò)調(diào)用 C 庫(kù) 系統(tǒng) IO 訪問(wèn)。

構(gòu)建文件系統(tǒng)

在上面介紹使用系統(tǒng) IO 的基本原理:通過(guò)重寫(xiě) _open/_write/_read 等接口,即可通過(guò) open/write/read 接口訪問(wèn)。

但是以上只提供了一系列系統(tǒng)接口,并將其與標(biāo)準(zhǔn) IO 綁定,可以使用 open/fopen 等函數(shù)進(jìn)行訪問(wèn),但是具體訪問(wèn)的數(shù)據(jù)依舊需要自己進(jìn)行實(shí)現(xiàn)。

在這次測(cè)試中我選用了 LittleFS 作為文件系統(tǒng),使用 RAM 中預(yù)分配的全局變量作為存儲(chǔ)介質(zhì),構(gòu)建了一個(gè)基于內(nèi)存的文件系統(tǒng)。(開(kāi)發(fā)板沒(méi)有 Flash 先用 RAM 代替了。。。)

其 _open 函數(shù)如下:

// 文件描述符列表,不包括標(biāo)準(zhǔn)輸入輸出, 最大 fd 為 FS_FILE_MAX + 3
lfs_file_t *g_file_list[FS_FILE_MAX] = {0};

int _open(const char *name, int flags)
{
  int i;
  int i_flags = 0;

  if ((flags & O_CREAT)  == O_CREAT)  i_flags |= LFS_O_CREAT;
  if ((flags & O_RDONLY) == O_RDONLY) i_flags |= LFS_O_RDONLY;
  if ((flags & O_WRONLY) == O_WRONLY) i_flags |= LFS_O_WRONLY;
  if ((flags & O_RDWR)   == O_RDWR)   i_flags |= LFS_O_RDWR;

  for (i = 0; i < FS_FILE_MAX; i++)
  {
    if (g_file_list[i] == NULL)
    {
      g_file_list[i] = malloc(sizeof(lfs_file_t));
      lfs_file_open(&g_lfs, g_file_list[i], name, i_flags);
      return i + 3;
    }
  }
  
  return -1;
}

其基本邏輯是將 open 傳入的參數(shù)轉(zhuǎn)換為 lfs_file_open 使用的參數(shù),傳入 lfs_file_oen, 然后分配一個(gè)空閑的文件描述符作為返回值。

在 _read 和 _write 接口中對(duì)文件描述符進(jìn)行判斷,當(dāng)文件描述符為 0/1/2 時(shí)將數(shù)據(jù)重定向到串口,否則從文件中讀寫(xiě)數(shù)據(jù)。代碼如下:

int _write(int fd, char *pBuffer, int size)
{
  int res = 0;

  if (fd == 1 || fd ==2)
  {
    HAL_UART_Transmit(&huart3, (uint8_t *)pBuffer, size, size);
  }
  else
  {
    res = lfs_file_write(&g_lfs, g_file_list[fd], pBuffer, size);
  }

  return res;
}

完成以上步驟后,便可以在程序中使用 open/read/write 等接口訪問(wèn)文件系統(tǒng)了,測(cè)試程序如下:

fs_init();

  write(STDOUT_FILENO, "system init ...n", 17);
  
  mkdir("/data", 0755);
  fd = open("/data/ascii.txt", O_CREAT|O_WRONLY);
  
  for (ch = 32; ch < 126; ch++)
  {
    write(fd, &ch, 1);
  }
  close(fd);

  fd = open("/data/ascii.txt", O_RDONLY);
  while (1)
  {
    char buff[16];
    int res = read(fd, buff, 16);
    if (res < 0)
    {
      close(fd);
      break; 
    }

    printf("system tick: %"PRIu32"n", HAL_GetTick());
    printf("read file data:%.*sn", 16, buff);
    HAL_Delay(500);
  }

程序下載燒錄后,使用串口工具查看到以下數(shù)據(jù):

圖片

移植的用途

關(guān)于在 STM32 中使用系統(tǒng) IO 的嘗試,主要是為了在 STM32 上移植一些 Linux 下的第三方庫(kù)。

他們很多都不可避免的使用了文件 IO 和 Posix 線程接口,對(duì)于 Posix 線程的接口在 FreeRTOS 中有提供,但是系統(tǒng) IO 卻沒(méi)有找到什么合適的方案,于是有了這樣的一種嘗試。

現(xiàn)在好像已經(jīng)有了更好的方案而不用去移植,不過(guò)使用這種方式的好處是以較少的代碼可以將系統(tǒng) IO 和標(biāo)準(zhǔn) IO 進(jìn)行關(guān)聯(lián)。

關(guān)于半主機(jī)模式

最后提一下半主機(jī)模式:這個(gè)實(shí)質(zhì)上是提供了一個(gè)在調(diào)試時(shí)訪問(wèn)主機(jī)數(shù)據(jù)的方法:

通過(guò)觸發(fā) SVC 指令,在 R0 寄存器中傳入需要的系統(tǒng)調(diào)用 ID, 在 R1 寄存器中傳入?yún)?shù)結(jié)構(gòu)體的指針。

通過(guò)調(diào)試器,可以在主機(jī)接受到對(duì)應(yīng)的系統(tǒng)調(diào)用,并進(jìn)行相應(yīng)的處理。

該測(cè)試程序整理好后,上傳到文末 閱讀原文 的 github 鏈接,或者發(fā)送 “測(cè)試代碼” 到公眾號(hào)后臺(tái)獲取源碼。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8691

    瀏覽量

    151919
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11345

    瀏覽量

    210396
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6895

    瀏覽量

    123745
  • STM32
    +關(guān)注

    關(guān)注

    2272

    文章

    10924

    瀏覽量

    357577
  • IO口
    +關(guān)注

    關(guān)注

    3

    文章

    170

    瀏覽量

    24200
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    標(biāo)準(zhǔn)IO的介紹

    標(biāo)準(zhǔn)IO由ANSI C標(biāo)準(zhǔn)定義在ANSI C標(biāo)準(zhǔn)中還定義了c庫(kù),用于提供一系列的函數(shù)標(biāo)準(zhǔn)IO就是
    發(fā)表于 04-26 09:53

    GPIO基本原理與寄存器配置基礎(chǔ)信息

    GPIO基本原理與寄存器配置基礎(chǔ)信息STM32F103ZET6,一共有7組IO口,每組IO口有16個(gè)IOUSART:(Universal Synchronous/Asynchronous
    發(fā)表于 08-16 07:56

    文件IO標(biāo)準(zhǔn)IO有何區(qū)別

    嵌入式Linux開(kāi)發(fā)系統(tǒng)開(kāi)發(fā)之《一節(jié)課搞懂文件IO標(biāo)準(zhǔn)IO
    發(fā)表于 11-04 06:42

    搞懂文件IO標(biāo)準(zhǔn)IO

    嵌入式Linux開(kāi)發(fā)系統(tǒng)開(kāi)發(fā)之《一節(jié)課搞懂文件IO標(biāo)準(zhǔn)IO
    發(fā)表于 12-16 08:18

    電源濾波器的基本原理和常用標(biāo)準(zhǔn)

    電源濾波器是電力電子技術(shù)中常用的一種裝置,用于去除電源中的噪聲和高頻干擾,保證電子設(shè)備的正常運(yùn)行。下面小編帶大家來(lái)了解一下電源濾波器的基本原理和常用標(biāo)準(zhǔn)。一、電源濾波器的基本原理電源濾波器是一種電路
    發(fā)表于 04-14 15:21

    AVR的IO結(jié)構(gòu)分析與操作

    AVR的IO是真正雙向IO結(jié)構(gòu),由于大部分網(wǎng)友都是從標(biāo)準(zhǔn)51轉(zhuǎn)過(guò)來(lái)的,受標(biāo)準(zhǔn)51的準(zhǔn)雙向IO和布爾操作概念影響,沒(méi)能掌握AVR的
    發(fā)表于 11-01 01:21 ?23次下載

    變跨導(dǎo)乘法器的基本原理

    變跨導(dǎo)乘法器的基本原理 圖5.4-25為變跨導(dǎo)乘法器原理圖。它利用V1、V2管的跨導(dǎo)GM正比于恒流源電流IO,而IO又受另一個(gè)輸入電壓控制,而實(shí)
    發(fā)表于 05-18 14:48 ?3283次閱讀
    變跨導(dǎo)乘法器的<b class='flag-5'>基本原理</b>

    網(wǎng)絡(luò)監(jiān)控的基本原理標(biāo)準(zhǔn)介紹

    網(wǎng)絡(luò)監(jiān)控的基本原理標(biāo)準(zhǔn)介紹
    發(fā)表于 11-08 17:46 ?88次下載

    如何使用io.Reader和io.Writer接口在程序中實(shí)現(xiàn)流式IO

    Go 語(yǔ)言標(biāo)準(zhǔn)庫(kù) io 包內(nèi)有一些常用接口和方法,本文配合圖片和實(shí)際代碼,詳細(xì)介紹了 io 包。 前言 在 Go 中,輸入和輸出操作是使用原語(yǔ)實(shí)現(xiàn)的,這些原語(yǔ)將數(shù)據(jù)模擬成可讀的或可寫(xiě)的字節(jié)流。 為此
    的頭像 發(fā)表于 07-29 16:46 ?3361次閱讀

    嵌入式Linux開(kāi)發(fā)系統(tǒng)開(kāi)發(fā)之《一節(jié)課搞懂文件IO標(biāo)準(zhǔn)IO

    嵌入式Linux開(kāi)發(fā)系統(tǒng)開(kāi)發(fā)之《一節(jié)課搞懂文件IO標(biāo)準(zhǔn)IO》http://www.makeru.com.cn/live/5413_2293.html?s=47236
    發(fā)表于 11-01 17:37 ?10次下載
    嵌入式Linux開(kāi)發(fā)<b class='flag-5'>系統(tǒng)</b>開(kāi)發(fā)之《一節(jié)課搞懂文件<b class='flag-5'>IO</b>與<b class='flag-5'>標(biāo)準(zhǔn)</b><b class='flag-5'>IO</b>》

    怎樣將IO設(shè)備分配給IO控制器?

    PROFINET IO 系統(tǒng)由一個(gè) PROFINET IO 控制器和其分配的 PROFINET IO 設(shè)備組成。當(dāng)添加了 IO 控制器和
    的頭像 發(fā)表于 12-21 09:57 ?3684次閱讀

    使用STM32F10xxx SWJ引腳作為標(biāo)準(zhǔn)IO

    本文介紹了如何使用GPIO固件庫(kù)來(lái)釋放SWJ-DP引腳(串行JTAG調(diào)試端口),并且重用為標(biāo)準(zhǔn)IO。SWJ-DP IO能夠用作標(biāo)準(zhǔn)IOs,它的性能可以達(dá)到
    的頭像 發(fā)表于 12-23 11:47 ?3087次閱讀

    多路IO復(fù)用模型和異步IO模型介紹

    多路 IO 復(fù)用模型 多路 IO 復(fù)用,有時(shí)也稱(chēng)為事件驅(qū)動(dòng) IO。它的基本原理就是有個(gè)函數(shù)會(huì)不斷地輪詢所負(fù)責(zé)的所有 socket ,當(dāng)某個(gè) socket有數(shù)據(jù)到達(dá)了,就通知用戶進(jìn)程。
    的頭像 發(fā)表于 10-08 17:21 ?849次閱讀
    多路<b class='flag-5'>IO</b>復(fù)用模型和異步<b class='flag-5'>IO</b>模型介紹

    信號(hào)驅(qū)動(dòng)IO與異步IO的區(qū)別

    一. 談信號(hào)驅(qū)動(dòng)IO (對(duì)比異步IO來(lái)看) 信號(hào)驅(qū)動(dòng)IO 對(duì)比 異步 IO進(jìn)行理解 信號(hào)驅(qū)動(dòng)IO: 內(nèi)核將數(shù)據(jù)準(zhǔn)備好的時(shí)候, 使用SIGIO
    的頭像 發(fā)表于 11-08 15:32 ?1134次閱讀
    信號(hào)驅(qū)動(dòng)<b class='flag-5'>IO</b>與異步<b class='flag-5'>IO</b>的區(qū)別

    電流倒灌揭秘:IO口損壞與系統(tǒng)故障的真相

    導(dǎo)讀本期文章將繼續(xù)深入了解電流倒灌,分析嵌入式系統(tǒng)IO口損壞和系統(tǒng)穩(wěn)定性問(wèn)題的根本原因。在上期的工程筆記中,我們了解了電流倒灌并探討了電流倒灌可能導(dǎo)致的一系列問(wèn)題,包括
    的頭像 發(fā)表于 12-11 11:38 ?433次閱讀
    電流倒灌揭秘:<b class='flag-5'>IO</b>口損壞與<b class='flag-5'>系統(tǒng)</b>故障的真相
    永利高百家乐官网开户| 兄弟百家乐的玩法技巧和规则 | 宝马会在线娱乐城| 百家乐博彩优惠论坛| 百家乐官网破解的方法| 聚龍社百家乐的玩法技巧和规则| 百家乐官网龙虎玩| 六合彩摇奖结果| 百家乐赌钱| 百家乐官网也能赢钱么| 郑州太阳城宾馆| 什么风水适合做生意| 金川县| 百家乐稳赢战术技巧| 察哈| 吕百家乐赢钱律| 百家乐接线玩法| 澳门百家乐官网怎样下注| 大发888游戏代充| 百家乐技巧论坛| 威尼斯人娱乐城优惠活动| 属虎属鼠做生意可以吗| 百家乐官网事电影| 棋牌游戏网| 百家乐娱乐备用网址| 赌百家乐官网到底能赌博赢| 澳门顶级赌场娱乐网| 百家乐2号破解下载| 包赢百家乐官网的玩法技巧和规则| 松滋市| 大发888客服端下载| 百家乐最低投注| 真人百家乐官网源代码| 金龍娱乐城| 威尼斯人娱乐城网址| 太阳百家乐官网管理网| 澳门百家乐官网心得玩博| bet365存| 大佬百家乐的玩法技巧和规则 | 皇冠备用投注网| 大发888最新网站|