Linux知識回顧總結----基礎IO

????????

目錄

1. 理解“文件”

????????1.1 文件的定義

2. 回顧 C 語言的文件操作

????????2.1 文件操作

2.2 實現cat

2.3? 可以實現打印的幾種方式

?3. 系統文件的IO

?3.2 使用系統的接口

?3.3 內部的實現

?3.4 重定向

4. 文件系統的內核結構

5. 緩沖區

????????5.1 是什么

5.2 為什么

5.3 有什么

5.4 見見緩沖區

? ? 6. 其他知識匯總

?6.1 FILE

?6.2 自己實現lib


?

1. 理解“文件”

? ??1.1 文件的定義

? ? ??文件具有狹義與廣義的定義。狹義的理解:存放在磁盤里面的文件。因為狹義的文件定義是在磁盤上的所以對于一切文件的操作就是對于外設的操作,就是對于外設的輸入與輸出簡稱為IO。

? ? ? ??廣義的文件:在 Linux 下一切皆文件。為什么一切皆文件呢?如何理解?Linux 認為一切皆文件也就是說操作系統將所有對于外設的操作都看成是對于文件的操作,這個的原因可以方便進程對于低下所有的不同外設進行管理(類似于多態的思想,結構體改變指針的指向)。盡管不同的外設的內部的具體方法以及函數不同但是都具有相同類型的函數,通過欺騙進程認為一切皆文件,然后達到用戶層同時認為一切皆文件。這個解釋通過后面看Linux的內核結構會更好理解。

2. 回顧 C 語言的文件操作

? ? ? ?2.1 文件操作

? ? ? ? 通過回顧C的具體的文件的接口操作,可以幫我們更好的理解操作系統的IO操作。下面展示一個文件的打開,關閉,追加,寫入,讀文件操作。

    FILE* fd = fopen("myfile.txt", "w");if(!fd){printf("fopen file\n");}//要寫入的需要使用write,先定義一個msg字符產const char* msg = "hello word\n";fwrite(msg, strlen(msg), 1, fd);
//展示讀的操作FILE* fd = fopen("myfile.txt", "r");if(!fd){printf("fopen file\n");}//讀需要使用buffer//printf("hello word\n");const char* msg = "hello word\n";char buffer[1024];// fread 參數含義:數據存放區,按照幾個字節讀取,讀多少,從哪里讀ssize_t s = fread(buffer, 1, 2, fd);if(s > 0){buffer[s] = 0; // 最后讀取的實際個數會存放在s中printf("%s", buffer);}
    //追加操作FILE* fd = fopen("myfile.txt", "a");if(!fd){printf("fopen file\n");}const char* msg = "hello word\n";fwrite(msg, strlen(msg), 1, fd);fclose(fd);

2.2 實現cat

? ? ? ? 通過對于上面代碼的簡單修改即可實現 cat 指令的具體內容。

#include <stdio.h>
#include <cstring>
int main(int argc,char* argv[])
{if(argc < 2){printf("you need write right formote:\n ./hello xxxx\n");return -1;}//使用讀的方式進行打開FILE* fd = fopen(argv[1], "r");char buffer[1024];while(1){//對于不確定的就要使用循環實現最后使用fopf進行判斷是否讀到了最后int s = fread(buffer, 1, sizeof(buffer), fd);if(s > 0){buffer[s] = 0;printf("%s", buffer);}if(feof(fd)){//讀到最后不能再讀了就要進行返回break;}}fclose(fd);return 0;
}

2.3? 可以實現打印的幾種方式

? ? ? ? 再屏幕上打印有三個常見的方式 fwrite, printf, fprintf。下面是實現的代碼。

	const char* msg = "hello djx\n";fwrite(msg, strlen(msg), 1, stdout);printf("%s", msg);fprintf(stdout, msg);

?3. 系統文件的IO

? ? ?3.1 標志位,文件描述符

? ? ? ? 標志位可以理解為使用位圖表示的一個數,通過宏定義的方式變成易讀的命名。這個標識位可以用來實現系統的打開以及其他的操作。

? ? ? ? ? ? ? ? 文件描述符:專門用來表示打開文件的數組下標,每打開一個文件就會形成一個文件描述符從3開始(因為os會自動占用0,1,2 表示標準輸入,標準輸出,標準錯誤)如果修改文件描述符指向(通過調用 dup2 這個函數)可以實現重定向。

?3.2 使用系統的接口

? ? ? ? 系統的接口主要是有 open, wirte, read 等。一下是詳細的解釋以及代碼。

    umask(0);//寫size_t fd = open("myfile", O_CREAT | O_WRONLY | O_TRUNC, 0666);const char* msg = "I am DJX\n";write(fd, msg, strlen(msg));//追加 size_t fd = open("myfile",  O_APPEND | O_WRONLY, 0666);const char* msg = "I am DJX\n";write(fd, msg, strlen(msg));close(fd);//讀size_t fd = open("myfile",  O_RDONLY , 0666);char buffer[1023];ssize_t s = read(fd, buffer, 123);if(s > 0){buffer[s] = 0;printf("%s", buffer);}close(fd);

? ? ? ? 需要注意的幾點是可以看到,我們主要看的是文件描述符 fd,然后我是以2進制,還是其他的讀法繼續寫入,或者是讀出都不關心,其實我們的語言層就是封裝了這些接口實現的 fwrte 等?。后面會有代碼來進行實現我自己封裝一個stdid。下圖表示的就是r,w等對應的文件的打開方式。

?

?3.3 內部的實現

? ? ? ? 我們說了這么多,其實在Linux的代碼中對于這么多打開的文件是對于進行了先描述,再組織的方式對于打開的文件文件進行了管理。在 task_struct 中具有 file_struct ,在 file_struct 中存放著文件描述表,通過文件描述表就可以找到已經打開了的 file。

3.4 重定向

? ? ? ? 有輸出重定向 > >>,一個是覆蓋式,另外一個為追加。?> 就是使用?O_CREAT | O_WRONLY | O_TRUNC 結合 dup2 將標準輸出定位到另外一個文件當中(本來應該打印到顯示器上,將 fd 新的文件描述符覆蓋到舊的文件描述符的上面, dup2(fd, 1))。

????????也就是說,我本來 printf是要打印到文件描述的 1 上面(也就是打印到顯示器上面)但是我現在改變了指向就讓其指向了 fd 這個文件描述符從而把東西打印到了文件里面,所以打開的文件需要以寫的方式進行打開。

? ? ? ? 輸入重定向:本來是要從 stdin 文件描述符為 0, 這個里面進行讀入數據,但是改變一下,讓另外的一個文件指向變成 0,也就是從這個文件里面讀到內容放到相應的位置,進行對應的操作。使用函數為dup2(fd, 0),打開的文件的方式為讀的方式打開從 stdin 中讀入,但是需要改變文件描述符;

4. 文件系統的內核結構

? ? ? ?在內核當中,可以看到 file 這個接口里面有一個 struct file_operations 的結構體,這個結構體定義了一個結構體指針,在這個結構體里面可以看到具有許多的函數指針,指向了不同設備的相同類型的操作,但是每個函數的具體操作是不相同的。類似于多態。? ? ?

????????

struct file 
{struct inode *f_inode; /* cached value */const struct file_operations *f_op;...atomic_long_t f_count; // 表?打開?件的引?計數,如果有多個?件指針指向它,就會增加f_count的值。unsigned int f_flags; // 表?打開?件的權限fmode_t f_mode; // 設置對?件的訪問模式,例如:只讀,只寫等。所 有的標志在頭?件<fcntl.h> 中定義loff_t f_pos; // 表?當前讀寫?件的位置...
}struct file_operations 
{struct module *owner;//指向擁有該模塊的指針;loff_t (*llseek) (struct file *, loff_t, int);//llseek ?法?作改變?件中的當前讀/寫位置, 并且新位置作為(正的)返回值.ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//?來從設備中獲取數據. 在這個位置的?個空指針導致 read 系統調?以 -EINVAL("Invalid argument") 失敗. ?個?負返回值代表了成功讀取的字節數( 返回值是?個"signed size" 類型, 常常是?標平臺本地的整數類型).ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//發送數據給設備. 如果 NULL, -EINVAL 返回給調? write 系統調?的程序. 如果?負,返回值代表成功寫的字節數.ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long,loff_t);//初始化?個異步讀 -- 可能在函數返回前不結束的讀操作.ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsignedlong, loff_t);//初始化設備上的?個異步寫.int (*readdir) (struct file *, void *, filldir_t);//對于設備?件這個成員應當為 NULL; 它?來讀取?錄, 并且僅對**?件系統**有?....
}

? ??????

? ? ? ? 這樣實現的目的前面也已經說過了,進程對于設備的管理也就變成了對于文件的管理,所以一切皆文件。更加深層次一點說就是,我們通過 file 這個結構體就可以調用 Linux 下面的所有資源。這便是一切皆文件!!!!

5. 緩沖區

? ? ? ? 5.1 是什么

? ? ? ? ?緩沖區簡單可以理解為:當我們進行打印一個東西的時候相關的數據會存放在一個區域中,當這個區域符合了一定的條件(比如緩沖區滿了放不下了不要刷新,強制刷新,進程退出,滿足了刷新條件)?就會將相關的內容給到os(操作系統),讓os完成相應的操作。

? ? ? ? ?官方的解釋為:內存中的一部分,也就是會預留出這一部分空間來進行數據的輸入與輸出,起到了一個緩沖的作用。緩沖區根據其對應的是輸?設備還是輸出設備,分為輸?緩沖區和輸出緩沖區。本章主要探討以及上面所說的就是輸出緩沖區。

5.2 為什么

? ? ? ? 它存在的意義就在于可以提高計算機的運行效率!

? ? ? ? 在理解他是如何如何提高效率之前,我們需要直到 os 去繼續工作(無論是進行打印,去磁盤中尋找文件)任何操作都會消耗資源,降低 計算機的速度。然后 緩沖區 就可以解決這個樣的問題。舉個例子:1. 我們需要打印一份東西,如何有一條打印語句就進行打印的話,他的效率遠遠不如我們將所有的要打印信息都放到一個內存中,然后對于這個內存進行統一的打印。 2. 向磁盤的文件讀取數據的時候我們一次性讀取大量的數據,然后放回到 os 中,可以極大的提高效率。

? ? ? ? 我們還可以把它理解為一個快遞驛站,將東西從一個地方運送到另外一個地方的時候,統一打包以及集中的繼續郵寄可以極大的提高我們想要郵寄東西需求。操作系統設計緩沖區的目的也在于此。

5.3 有什么

? ? ? ? 根據類型的分類可以分為:行緩沖區(打印到\n 的時候就進行打印,調用系統), 全緩沖區(滿整個緩沖區后才進?I/O系統調?操作。),?緩沖區(標準I/O庫不對字符進?緩存,直接調?系統調?。)

? ? ? ? 下列特殊情況也會引發緩沖區的刷新:1. 緩沖區滿時;2. 執?flush語句 3. 進程結束

?5.4 見見緩沖區

? ? ? ? 下面一段代碼,會有不一樣的結果請看。

#include <stdio.h>
#include <cstring>
#include <unistd.h>
int main()
{const char* msg1 = "hello print\n";const char* msg2 = "hello fwrite\n";const char* msg3 = "hello write\n";printf("%s", msg1);fwrite(msg2, strlen(msg2), 1, stdout);write(1, msg3, strlen(msg3));fork();
}

????????最后跑出來結果為,可以看到 當對于程序的內容進行重定向放到myfile中時,首先使用的是write因為這是一個系統的函數,直接放到了顯示器上面,然后后面的 print 和 fwrite 打印了兩次是因為當我們進行重定向的時候會修改文件的刷新方式,從行緩沖(因為有 \n )變成了 文件緩沖。也就是這個 p 和 fwrite 的打印的內容都在緩沖區當中,然后子進程(對于父進程代碼的一份拷貝)結束了講緩沖區的內容刷新到了操作系統進行打印,然后是父進程結束刷新緩沖區,進行打印。

?????????但是當我們進行普通的使用的時候(也就是運行程序的時候顯示的就還是行緩沖)遇到 \n 就會進行打印。?

? ? ? ?

? ? ? ? 將沒有fork的重定向到文件當中。會先使用系統函數write。

? ? ? ? 這樣的例子就很好的說明了緩沖區對于磁盤文件的使用,以及在進行打印時候的作用。?

? ? 6. 其他知識匯總

? ? ? ? 6.1 FILE

? ? ? ? ? ? ?它是c語言庫中使用文件操作的數據類型,那么它究竟是什么??沒錯他就是一個結構體,里面進行封裝了系統調用函數需要的文件描述符 fd。原碼的結構如下:

{#define _IO_file_flags _flags//緩沖區相關/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr; /* Current read pointer */char* _IO_read_end; /* End of get area. */char* _IO_read_base; /* Start of putback+get area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr; /* Current put pointer. */char* _IO_write_end; /* End of put area. */char* _IO_buf_base; /* Start of reserve area. */char* _IO_buf_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area*/char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封裝的?件描述符#if 0int _blksize;#elseint _flags2;#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small. */#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock;#ifdef _IO_USE_OLD_IO_FILE}

6.2 自己實現lib

? ? ? ? 里面需要實現 fwrite(使用系統 open ,以寫入,或者是追加的方式進行打開), fopen,fclose, fflush。下章對于這部分代碼進行說明。

#include "mystdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>static MyFile *BuyFile(int fd, int flag)
{MyFile *f = (MyFile*)malloc(sizeof(MyFile));if(f == NULL) return NULL;f->bufferlen = 0;f->fileno = fd;f->flag = flag;f->flush_method = LINE_FLUSH;memset(f->outbuffer, 0, sizeof(f->outbuffer));return f;
}MyFile *MyFopen(const char *path, const char *mode)
{int fd = -1;int flag = 0;if(strcmp(mode, "w") == 0){flag = O_CREAT | O_WRONLY | O_TRUNC;fd = open(path, flag, 0666);}else if(strcmp(mode, "a") == 0){flag = O_CREAT | O_WRONLY | O_APPEND;fd = open(path, flag, 0666);}else if(strcmp(mode, "r") == 0){flag = O_RDWR;fd = open(path, flag);}else{//TODO}if(fd < 0) return NULL;return BuyFile(fd, flag);
}
void MyFclose(MyFile *file)
{if(file->fileno < 0) return;MyFFlush(file);close(file->fileno);free(file);
}
int MyFwrite(MyFile *file, void *str, int len)
{// 1. 拷貝memcpy(file->outbuffer+file->bufferlen, str, len);file->bufferlen += len;// 2. 嘗試判斷是否滿足刷新條件!if((file->flush_method & LINE_FLUSH) && file->outbuffer[file->bufferlen-1] == '\n'){MyFFlush(file);}return 0;
}
void MyFFlush(MyFile *file)
{if(file->bufferlen <= 0) return;// 把數據從用戶拷貝到內核文件緩沖區中int n = write(file->fileno, file->outbuffer, file->bufferlen);(void)n;fsync(file->fileno);file->bufferlen = 0;
}

??????????以上是對于IO的回顧。這個文章用于我的學習記錄,如果是有其他的錯誤還請批評指正。如果對你有幫助還請給我點個贊👍👍👍。?????

????????????????

?????????

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916656.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916656.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916656.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡:基礎概念

網絡&#xff1a;基礎概念 在計算機發展過程中&#xff0c;最開始每個計算機時相互獨立的&#xff0c;后來人們需要用計算機合作處理任務&#xff0c;這就牽扯到了數據交換&#xff0c;所以最開始的網絡就誕生了。一開始&#xff0c;網絡都是局域網LAN&#xff0c;后來技術成熟…

圖像識別邊緣算法

文章目錄1. 基本概念2. 邊緣檢測原理邊緣類型&#xff1a;3. 常見邊緣檢測算法3.1 Sobel算子3.2 Canny邊緣檢測3.3 Laplacian算子4. Canny邊緣檢測詳細流程流程圖示例&#xff1a;詳細步驟說明&#xff1a;5. 邊緣檢測算法比較6. 參數調優建議Canny邊緣檢測參數&#xff1a;Sob…

【Java Web實戰】從零到一打造企業級網上購書網站系統 | 完整開發實錄(終)

&#x1f9ea; 測試與質量保證 &#x1f50d; 全方位測試體系 我建立了企業級的全方位測試體系來確保系統質量&#xff1a; &#x1f9ea; 測試金字塔模型 #mermaid-svg-u4I8UuUAyxJVjcqs {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill…

QT開發---網絡編程下

HTTP協議 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;是互聯網上應用最為廣泛的協議之一&#xff0c;用于客戶端和服務器之間的通信。默認端口80&#xff0c;傳輸層使用的是TCP協議特點無連接&#xff1a;HTTP協議是無連接的&#xff…

mac 蘋果電腦 Intel 芯片(Mac X86) 安卓虛擬機 Android模擬器 的救命稻草(下載安裝指南)

引言&#xff1a; 還在為你的Intel芯片MacBook&#xff08;i5, i7, i9等&#xff09;找不到合適的安卓虛擬機而發愁嗎&#xff1f;隨著Apple Silicon (M1/M2/M3) 芯片的普及&#xff0c;大量優秀的安卓模擬器&#xff08;如Android Studio自帶的模擬器、網易MuMu等&#xff09;…

C語言:順序表(上)

C語言&#xff1a;順序表&#xff08;上&#xff09; 1.順序表的介紹 2.順序表的實現 1.順序表的介紹 線性表是n個具有相同特性的數據元素的有限序列。 線性表是一種在實際中廣泛使用的數據結構&#xff0c;常見的線性表&#xff1a;順序表、鏈表、棧、隊列、字符串… 線性表在…

GPT - 5被曝將在8月初發布!并同步推出mini、nano版

據《TheVerge》最新報道&#xff0c;OpenAI 正準備在 8 月發布新版本旗艦大模型 GPT-5&#xff0c;如果順利的話發布節點最早會在 8 月初。同時&#xff0c;下個月發布 GPT-5 時&#xff0c;還會一并推出 mini&#xff08;小型&#xff09;和 nano&#xff08;微型&#xff09;…

【Linux操作系統】簡學深悟啟示錄:Linux環境基礎開發工具使用

文章目錄1.軟件包管理器yum2.Linux編輯器vim2.1 三模式切換2.2 正常模式2.3 底行模式2.4 可視化模式2.5 vim 配置3.Linux編譯器gcc/g3.1 預處理3.2 編譯3.3 匯編3.4 連接3.5 函數庫4.Linux自動化構建工具Makefile5.Linux調試器gdb希望讀者們多多三連支持小編會繼續更新你們的鼓…

八大神經網絡的區別

神經網絡名稱全稱/修正名稱主要作用核心特點典型應用場景CINICNN&#xff08;卷積神經網絡&#xff09;處理圖像、視頻等空間數據&#xff0c;提取局部特征。使用卷積核、池化操作&#xff1b;擅長平移不變性。圖像分類、目標檢測、人臉識別。RINIRNN&#xff08;循環神經網絡&…

從 SQL Server 到 KingbaseES V9R4C12,一次“無痛”遷移與深度兼容體驗實錄

#數據庫平替用金倉 #金倉產品體驗官 摘要&#xff1a;本文以體驗項目案例為主線&#xff0c;從下載安裝、數據類型、T-SQL、JDBC、性能基準、踩坑回退六大維度&#xff0c;全景驗證 KingbaseES V9R4C12 對 SQL Server 的“零改造”兼容承諾&#xff1b;并給出 TPCH 100G 性能對…

EasyPlayer播放器系列開發計劃2025

EasyPlayer系列產品發展至今&#xff0c;已經超過10年&#xff0c;從最早的EasyPlayer RTSP播放器&#xff0c;到如今維護的3條線&#xff1a;EasyPlayer-RTSP播放器&#xff1a;Windows、Android、iOS&#xff1b;EasyPlayerPro播放器&#xff1a;Windows、Android、iOS&#…

通信名詞解釋:I2C、USART、SPI、RS232、RS485、CAN、TCP/IP、SOCKET、modbus等

以下內容參考AI生成內容1. I2C&#xff08;Inter-Integrated Circuit&#xff0c;集成電路間總線&#xff09;定義&#xff1a;由飛利浦&#xff08;現恩智浦&#xff09;開發的短距離串行通信總線&#xff0c;用于芯片級設備間的低速數據傳輸。工作原理&#xff1a;采用兩根信…

bash的特性-常見的快捷鍵

一、前言在 Linux Shell 編程和日常使用中&#xff0c;Bash 快捷鍵 是提升命令行操作效率的利器。熟練掌握這些快捷鍵&#xff0c;不僅可以節省大量輸入時間&#xff0c;還能顯著提升你在終端環境下的操作流暢度。本文將帶你全面了解 Bash 中常用的快捷鍵&#xff0c;包括&…

【Java Web實戰】從零到一打造企業級網上購書網站系統 | 完整開發實錄(三)

&#x1f3a8; 核心功能設計 &#x1f464; 用戶管理系統 用戶管理是整個系統的基礎&#xff0c;我設計了完整的用戶生命周期管理&#xff1a; &#x1f510; 用戶注冊流程 #mermaid-svg-D0eUHWissjNhkqlB {font-family:"trebuchet ms",verdana,arial,sans-serif;fon…

uniapp input 聚焦時鍵盤彈起滾動到對應的部分

實現效果代碼如下<template><view idapp><view class"aa"></view><iconfont name"left"></iconfont>姓氏&#xff1a;<input style"background-color: antiquewhite;" type"text" v-model&quo…

【基礎篇三】WebSocket:實時通信的革命

目錄 一、傳統HTTP的"痛點"分析 1.1 HTTP的單向通信模式 1.2 "實時"效果的痛苦嘗試 ?編輯 1.3 性能對比分析 二、WebSocket 協議詳解 2.1 WebSocket是什么&#xff1f; ?編輯 2.2 WebSocket的核心特性 2.2.1 全雙工通信&#xff08;Full-Duple…

設計模式(十八)行為型:中介者模式詳解

設計模式&#xff08;十八&#xff09;行為型&#xff1a;中介者模式詳解中介者模式&#xff08;Mediator Pattern&#xff09;是 GoF 23 種設計模式中的行為型模式之一&#xff0c;其核心價值在于通過引入一個中介者對象來封裝一組對象之間的交互&#xff0c;從而降低對象間的…

Upload-Labs通關全攻略詳細版

前端校驗繞過:pass 01 兩種思路:1.通過抓包,修改后綴 2.前端禁用js繞過前端后綴檢驗 首先寫一個木馬,改為圖片格式GIF89a<?php eval($_POST[cmd])?>抓包之后改為PHP格式: 使用蟻劍連接木馬,第一次嘗試一直是返回數據為空,原因是沒有鏈接到木馬,于是尋找木馬地址…

C#觀察者模式示例代碼

using System; using System.Collections.Generic; using System.Threading;namespace RefactoringGuru.DesignPatterns.Observer.Conceptual {// Observer觀察者 也可以叫做訂閱者 subscriberspublic interface IObserver{// Receive update from subject// 接收來自主題的更新…

電子電子架構 --- 軟件項目的開端:裁剪

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…