1. Linux系統(tǒng)只能通過(guò)系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。 Printk()是內(nèi)核使用的函數(shù) 2. 模塊加載 Linux內(nèi)核模塊加載函數(shù)一般以_ _init標(biāo)識(shí)聲明,模塊加載函數(shù)必須以module_init( 函數(shù)名)的形式被指定。 3. Linux內(nèi)核的配置系統(tǒng)由以下三部分組成: Makefile:分布在Linux內(nèi)核源代碼中的makefile,定義Linux內(nèi)核的編譯規(guī)則。 配置文件Kconfig:給用戶提供配置選擇的功能。 配置工具:包括配置命令解釋器和配置用戶界面。 使用make config/make menuconfig命令后,會(huì)生成一個(gè).config配置文件,記錄 哪些部分被編譯入內(nèi)核,哪些部分被編譯為內(nèi)核模塊 在Linux內(nèi)核中增加程序需要完成以下三項(xiàng)工作: 將編寫(xiě)的源代碼復(fù)制到Linux內(nèi)核源代碼的相應(yīng)目錄。 在目錄的Kconfig文件中增加新源代碼對(duì)應(yīng)項(xiàng)目的編譯配置選項(xiàng)。 在目錄的Makefile文件中增加對(duì)新源代碼的編譯條目。 4. 目標(biāo)定義用來(lái)定義哪些內(nèi)容要作為模塊編譯,哪些要編譯并連接進(jìn)內(nèi)核。 obj-y +=foo.o 表示要由foo.c或foo.s文件編譯得到foo.o并連接進(jìn)內(nèi)核,而obj-m則表示該文件要 作為模塊編譯。除了y,m以外的obj-x形式的目標(biāo)都不會(huì)被編譯。 更常見(jiàn)的做法是根據(jù).config文件的CONFIG_變量來(lái)決定文件的編譯方式. 5. Linux總共用5個(gè)數(shù)字來(lái)表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID,第二位表示設(shè) 置組ID,第三位表示用戶自己的權(quán)限位,第四位表示組的權(quán)限,第五位表示其他人的 權(quán)限。每個(gè)數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫(xiě)權(quán)限)、4(讀權(quán)限)、0(無(wú))或者是 這些值的和。 6. int read(int fd,const void *buf,size_t length); 實(shí)現(xiàn)從fd指定的文件中讀取length個(gè)字節(jié)到buf指向的緩沖區(qū)中,返回值為實(shí)際讀 取的字節(jié)數(shù)( 讀到緩沖區(qū)中 fd-->buf) int write(int fd,const void *buf,size_t length); 從緩沖區(qū)buf寫(xiě)length個(gè)字節(jié)到fd指向的文件中,返回實(shí)際寫(xiě)入的字節(jié)數(shù)。 (寫(xiě)到文件中 buf-->fd) 7. int open(pathname,o_CREAT | O_WRONLY | O_TRUNC,mode) int lseek(int fd,offset_t offset,int whence); 定位:該函數(shù)將文件讀寫(xiě)指針相對(duì)whence移動(dòng)offset個(gè)字節(jié)。操作成功時(shí),返回文件 指針相對(duì)于文件頭的位置。 關(guān)閉 int close(int fd); 8. C庫(kù)函數(shù)的文件操作是獨(dú)立于具體的操作系統(tǒng)平臺(tái)的,不管是在DOS、Windows、Linux 還是在VxWorks中都是這些函數(shù)。 創(chuàng)建和打開(kāi) FILE *fopen(const char *path,const char *mode); 9.文件系統(tǒng) sbin:系統(tǒng)管理類命令可執(zhí)行文件的存放位置 proc:這是Linux的一個(gè)特殊文件系統(tǒng),主要用于存放內(nèi)核及進(jìn)程信息 10、udev設(shè)備文件系統(tǒng) Udev完全在用戶態(tài)工作,利用設(shè)備加入或移除時(shí)內(nèi)核所發(fā)送的熱插拔事件來(lái)工作。 Udev的設(shè)計(jì)目標(biāo): 在用戶空間中執(zhí)行 動(dòng)態(tài)建立/刪除設(shè)備文件 允許每個(gè)都不用關(guān)心主/次設(shè)備號(hào) 提供LSB標(biāo)準(zhǔn)名稱 如果需要,可提供固定的名稱 Udev的工作過(guò)程 當(dāng)內(nèi)存檢測(cè)到在系統(tǒng)中出現(xiàn)了新設(shè)備后,內(nèi)核會(huì)在sysfs文件系統(tǒng)中為該新設(shè)備生成新 的記錄并導(dǎo)出一些設(shè)備特定的信息及所發(fā)生的事情 Udev獲取內(nèi)核導(dǎo)出的信息,它調(diào)用namedev決定應(yīng)該給該設(shè)備指定的 在namedev中使用5個(gè)步驟來(lái)決定指定設(shè)備的命名 標(biāo)簽/序號(hào) 設(shè)備總線號(hào) 總線上的拓?fù)?br>替換名稱 內(nèi)核提供的名稱 11.select Select入口點(diǎn) (1)Select函數(shù)檢查設(shè)備,看數(shù)據(jù)是否可讀取或設(shè)備是否可用于寫(xiě)數(shù)據(jù)。 (2)系統(tǒng)調(diào)用在檢查與設(shè)備文件相關(guān)的文件描述符時(shí),使用select入口點(diǎn)。 (3)如果驅(qū)動(dòng)程序沒(méi)有提供select入口,select操作將認(rèn)為設(shè)備已經(jīng)準(zhǔn)備好進(jìn)行任何 I/O操作。 12.kmalloc 在設(shè)備驅(qū)動(dòng)程序中動(dòng)態(tài)開(kāi)辟內(nèi)存,不是簡(jiǎn)單地用malloc(返回線性地址),而是用 kmalloc(返回物理地址),或者用get_free_pages直接申請(qǐng)頁(yè)。釋放內(nèi)存用的是 kfree或free_pages。 13. #include <fcntl.h> // open() close() #include <unistd.h> // read() write() #define DEVICE_NAME "/dev/gpio_led_ctl" 14. 單片機(jī)處理中斷: (1)分辨是哪一個(gè)中斷 (2)調(diào)用中斷處理函數(shù) (3)清中斷 15. linux處理中斷: 詳見(jiàn)P418 asm_do_IRQ 中斷總?cè)肟诤瘮?shù) desc->handle_irq() irq_desc[irq] 數(shù)組 里面有 { handle_irq=handle_edge_irq chip=s3c_irq_eint0t04 } irq_desc[Eint4-Eint23] {handle_irq=handle_edge_irq chip=s3c_irq_chip } 上面這些都是在s3c24**_init_irq,即中斷初始化函數(shù)上做的。 再來(lái)看下handle_edge_irq函數(shù) (1)desc->chip_ack(irq) 響應(yīng)中斷,也就是清中斷 (2)handle_IRQ_event 處理中斷 取出action鏈表中的成員,執(zhí)行action->handler 按下按鍵的過(guò)程: (1)進(jìn)入異常模式 b vector_irq + 偏移量 (2)__irq_usr (3)b asm_do_IRQ (4)irq_desc[irq]->handle_irq (5)handle_edge_irq(處理上面二個(gè)過(guò)程) 16. 申請(qǐng)中斷:request_irq(irq,handler,irqflags,devname.dev_id) (1)分配irqaction結(jié)構(gòu) (2)setup_irq(irq,action) a.把上面的結(jié)構(gòu)放入irq_desc[irq]->action 鏈表中 b.desc->chip->settype() 設(shè)置引腳 c.desc->chip->startup/enable 使能中斷 釋放中斷:free_irq(irq,dev_id) 出鏈,禁止中斷 17. exec 5</dev/buttons打開(kāi)中斷設(shè)備 exec 5<&-關(guān)閉中斷設(shè)備 cat /proc/interrupts 查看中斷設(shè)備 ps:查看進(jìn)程 ls -l /proc/771/fd (771為中斷的進(jìn)程號(hào)) 執(zhí)行后可以查看到/dev/buttons設(shè)備
|