




已閱讀5頁,還剩148頁未讀, 繼續(xù)免費閱讀
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
嵌入式Linux應用程序設計 1 主要內(nèi)容 嵌入式LinuxC語言程序開發(fā)基礎文件I O編程進程與線程網(wǎng)絡編程動態(tài)庫與靜態(tài)庫串口編程 2 11 1嵌入式LinuxC語言應用程序開發(fā)基礎 編寫源程序工具vimgedit 3 VIM相關的操作命令 文件打開相關命令 在終端窗口中使用 vifilename 打開或新建文件 并將光標置于第一行首vi nfilename 打開文件并將光標置于第n行首vi filename 打開文件 并將光標置于最后一行首vi patternfilename 打開文件 并將光標置于第一個與pattern匹配的串處vi rfilename 在上次征用vi編輯時發(fā)生系統(tǒng)崩潰 恢復filenamevifilename filename 打開多個文件 依次進行編輯 4 VIM相關的操作命令 VIM光標操作類命令 VIM界面中使用 h或BackSpace 光標左移一個字符L或space 光標右移一個字符k或Ctrl p 光標上移一行j或Ctrl n 光標下移一行Enter 光標下移一行W或w 光標右移一個字至字首B或b 光標左移一個字至字首E或e 光標右移一個字至字尾 5 VIM相關的操作命令 屏幕操作類命令 Ctrl u 向文件首翻半頁Ctrl d 向文件尾翻半頁Ctrl f 向文件尾翻一屏Ctrl b 向文件首翻一屏 6 VIM相關的操作命令 插入文本類命令刪除操作相關命令搜索及替換命令選項設置底行模式命令文本緩存操作 7 11 1嵌入式LinuxC語言應用程序開發(fā)基礎 調(diào)試程序建立GDB組建調(diào)試運行調(diào)試命令 8 11 2系統(tǒng)調(diào)用與文件I O編程 1 1 Linux系統(tǒng)調(diào)用所謂系統(tǒng)調(diào)用是指操作系統(tǒng)提供給用戶程序的一組 特殊 接口 用戶程序可以通過這組 特殊 接口來獲得操作系統(tǒng)內(nèi)核提供的特殊服務 在linux中用戶程序不能直接訪問內(nèi)核提供的服務 為了更好的保護內(nèi)核空間 將程序的運行空間分為內(nèi)核空間和用戶空間 他們運行在不同的級別上 在邏輯上是相互隔離的 9 11 2系統(tǒng)調(diào)用與文件I O編程 1 2 用戶程序接口 API 在linux中用戶編程接口 API 遵循了在UNIX中最流行的應用編程界面標準 POSIX標準 這些系統(tǒng)調(diào)用編程接口主要通過C庫 libc 實現(xiàn)的 10 11 2系統(tǒng)調(diào)用與文件I O編程 圖1系統(tǒng)調(diào)用 API與系統(tǒng)命令之間的關系 11 11 2系統(tǒng)調(diào)用與文件I O編程 2 1 文件I O介紹可用的文件I O函數(shù) 打開文件 讀文件 寫文件等等 大多數(shù)linux文件I O只需用到5個函數(shù) open read write lseek以及close 不帶緩存指的是每個read和write都調(diào)用內(nèi)核中的一個系統(tǒng)調(diào)用 這些不帶緩存的I O函數(shù)不是ANSIC的組成部分 但是POSIX組成部分 12 11 2系統(tǒng)調(diào)用與文件I O編程 2 2文件描述符對于內(nèi)核而言 所有打開文件都由文件描述符引用 文件描述符是一個非負整數(shù) 當打開一個現(xiàn)存文件或創(chuàng)建一個新文件時 內(nèi)核向進程返回一個文件描述符 當讀 寫一個文件時 用open或creat返回的文件描述符標識該文件 將其作為參數(shù)傳送給read或write 13 11 2系統(tǒng)調(diào)用與文件I O編程 2 3open函數(shù) include include includeintopen constchar pathname intoflag mode tmode 返回 若成功為文件描述符 若出錯為 1 14 11 2系統(tǒng)調(diào)用與文件I O編程 2 4creat函數(shù) 可用creat函數(shù)創(chuàng)建一個新文件 include include includeintcreat constchar pathname mode tmode 返回 若成功為只寫打開的文件描述符 若出錯為 1 注意 此函數(shù)等效于 open pathname O WRONLY O CREAT O TRUNC mode creat的一個不足之處是它以只寫方式打開所創(chuàng)建的文件 15 11 2系統(tǒng)調(diào)用與文件I O編程 2 5close函數(shù) 可用close函數(shù)關閉一個打開文件 includeintclose intfiledes 返回 若成功為0 若出錯為 1當一個進程終止時 它所有的打開文件都由內(nèi)核自動關閉 很多程序都使用這一功能而不顯式地用close關閉打開的文件 16 11 2系統(tǒng)調(diào)用與文件I O編程 2 6lseek函數(shù) 每個打開文件都有一個與其相關聯(lián)的 當前文件偏移量 它是一個非負整數(shù) 用以度量從文件開始處計算的字節(jié)數(shù) 通常 讀 寫操作都從當前文件偏移量處開始 并使偏移量增加所讀或?qū)懙淖止?jié)數(shù) 按系統(tǒng)默認 當打開一個文件時 除非指定O APPEND選擇項 否則該位移量被設置為0 可以調(diào)用lseek顯式地定位一個打開文件 17 11 2系統(tǒng)調(diào)用與文件I O編程 2 7read函數(shù) 用read函數(shù)從打開文件中讀數(shù)據(jù) includessize tread intfeledes void buff size tnbytes 返回 讀到的字節(jié)數(shù) 若已到文件尾為0 若出錯為 1 如read成功 則返回讀到的字節(jié)數(shù) 如已到達文件的尾端 則返回0 18 11 2系統(tǒng)調(diào)用與文件I O編程 2 8write函數(shù) 用write函數(shù)向打開文件寫數(shù)據(jù) includessize twrite intfiledes constvoid buff size tnbytes 返回 若成功為已寫的字節(jié)數(shù) 若出錯為 1 其返回值通常與參數(shù)nbytes的值不同 否則表示出錯 write出錯的一個常見原因是 磁盤已寫滿 或者超過了對一個給定進程的文件長度限制 19 11 2系統(tǒng)調(diào)用與文件I O編程 2 9fcntl函數(shù) fcntl函數(shù)可以改變已經(jīng)打開文件的性質(zhì) include include includeintfcntl intfiledes intcmd 返回 若成功則依賴于cmd 見下 若出錯為 1 20 11 2系統(tǒng)調(diào)用與文件I O編程 fcntl函數(shù)有五種功能 復制一個現(xiàn)存的描述符 新文件描述符作為函數(shù)值返 cmd F DUPFD 獲得 設置文件描述符標記 對應于filedes的文件描述符標志作為函數(shù)值返回 cmd F GETFD或F SETFD 獲得 設置文件狀態(tài)標志 對應于filedes的文件狀態(tài)標志作為函數(shù)值返回 cmd F GETFL或F SETFL 獲得 設置異步I O所有權 cmd F GETOWN或F SETOWN 獲得 設置記錄鎖 cmd F SETLK F SETLKW 21 11 2系統(tǒng)調(diào)用與文件I O編程 文件狀態(tài) 標志說明 22 11 2系統(tǒng)調(diào)用與文件I O編程 2 10ioctl函數(shù) ioctl函數(shù)是I O操作的雜物箱 不能用上述函數(shù)表示的I O操作通常都能用ioctl表示 終端I O是ioctl的最大使用方面 主要用于設備的I O控制 include SVR4 include 4 3 BSD intioctl intfiledes intrequest 返回 若出錯則為 1 若成功則為其他值 23 11 3Linux進程控制 1 程序和進程 24 1 程序和進程 1 1程序程序 program 是存放在磁盤文件中的可執(zhí)行文件 1 2進程和進程ID程序的執(zhí)行實例被稱為進程 process 某些操作系統(tǒng)用任務表示正被執(zhí)行的程序 每個linux進程都一定有一個唯一的數(shù)字標識符 稱為進程ID processID 進程ID總是一非負整數(shù) 25 1 3linux下的進程結構 Linux系統(tǒng)是一個多進程的系統(tǒng) 進程之間具有并行性 互不干擾的特點 linux中進程包含3個段 分別為 代碼段 數(shù)據(jù)段 和 堆棧段 代碼段 數(shù)據(jù)段 堆棧段 26 數(shù)據(jù)段 存放全局變量 常數(shù)以及動態(tài)數(shù)據(jù)分配的空間 malloc函數(shù)取得的空間 代碼段 存放程序代碼 堆棧段 存放子程序的返回地址 子程序的參數(shù)以及程序的局部變量 27 1 3init進程 進程ID為1通常是init進程 在自舉過程結束時由內(nèi)核調(diào)用 init進程絕不會終止 它是一個普通的用戶進程 與交換進程不同 它不是內(nèi)核中的系統(tǒng)進程 但是它以超級用戶特權運行 28 1 4獲取進程標識 include includepid tgetpid void 返回 調(diào)用進程的進程IDpid tgetppid void 返回 調(diào)用進程的父進程IDuid tgetuid void 返回 調(diào)用進程的實際用戶IDuid tgeteuid void 返回 調(diào)用進程的有效用戶IDgid tgetgid void 返回 調(diào)用進程的實際組IDgid tgetegid void 返回 調(diào)用進程的有效組ID 29 1 5fork函數(shù) include includepid tfork void 返回 子進程中為0 父進程中為子進程ID 出錯為 1 30 1 6進程創(chuàng)建 由fork創(chuàng)建的新進程被稱為子進程 childprocess 該函數(shù)被調(diào)用一次 但返回兩次 兩次返回的區(qū)別是子進程的返回值是0 而父進程的返回值則是子進程的進程ID 一般來說 在fork之后是父進程先執(zhí)行還是子進程先執(zhí)行是不確定的 這取決于內(nèi)核所使用的調(diào)度算法 31 1 6進程創(chuàng)建 使用fork函數(shù)得到的子進程是父進程的處繼承了整個進程的地址空間 包括 進程上下文 進程堆棧 內(nèi)存信息 打開的文件描述符 信號控制設置 進程優(yōu)先級 進程組號 當前工作目錄 根目錄 資源限制 控制終端等 32 1 7vfork函數(shù) vfork函數(shù)的調(diào)用序列和返回值與fork相同 但兩者的語義不同 現(xiàn)在很多的實現(xiàn)并不做一個父進程數(shù)據(jù)段和堆的完全拷貝 因為在fork之后經(jīng)常跟隨著exec 作為替代 使用了在寫時復制 copy on Write COW 的技術 這些區(qū)域由父 子進程共享 而且內(nèi)核將它們的存取許可權改變?yōu)橹蛔x的 如果有進程試圖修改這些區(qū)域 則內(nèi)核為有關部分 典型的是虛存系統(tǒng)中的 頁 做一個拷貝 如 uclinux中的進程創(chuàng)建 33 copy on Write技術 34 1 8exec函數(shù) 在用fork函數(shù)創(chuàng)建子進程后 子進程往往要調(diào)用一種exec函數(shù)以執(zhí)行另一個程序 當進程調(diào)用一種exec函數(shù)時 該進程完全由新程序代換 而新程序則從其main函數(shù)開始執(zhí)行 因為調(diào)用exec并不創(chuàng)建新進程 所以前后的進程ID并未改變 exec只是用另一個新程序替換了當前進程的正文 數(shù)據(jù) 堆和棧段 35 1 8exec函數(shù) includeintexecl constchar pathname constchar arg0 char 0 intexecv constchar pathname char constargv intexecle constchar pathname constchar arg0 char 0 char constenvp intexecve constchar pathnamechar constargv char constenvp intexeclp constchar pathname constchar arg0 char 0 intexecvp constchar pathname char constargv 六個函數(shù)返回 若出錯則為 1 若成功則不返回 36 1 8exec函數(shù) 參數(shù)表的傳遞有關 l表示表 list v表示矢量 vector e 可傳遞新進程環(huán)境變量 execle execve p 可執(zhí)行文件查找方式為文件名 execlp execvp 例如 execlp c execl c execle c execve c 37 1 9exit和 exit exit和 exit用于中止進程 exit的作用 直接使進程停止運行 清除其使用的內(nèi)存空間 并清除其在內(nèi)核中的數(shù)據(jù)結構 exit與 exit函數(shù)不同 exit函數(shù)在調(diào)用exit系統(tǒng)之前要檢查文件打開情況把文件緩沖區(qū)的內(nèi)容寫回文件中去 如調(diào)用printf 函數(shù) 38 exit exit 39 1 10wait和waitpid函數(shù) 當一個進程正常或異常終止時 內(nèi)核就向其父進程發(fā)送SIGCHLD信號 因為子進程終止是個異步事件 這可以在父進程運行的任何時候發(fā)生 所以這種信號也是內(nèi)核向父進程發(fā)的異步通知 父進程可以忽略該信號 或者提供一個該信號發(fā)生時即被調(diào)用執(zhí)行的函數(shù) 信號處理程序 對于這種信號的系統(tǒng)默認動作是忽略它 wait函數(shù)用于使父進程阻塞 直到一個子進程結束或者該進程接收到一個指定信號為止 40 include includepid twait int status pid twaitpid pid tpid int status intoptions 兩個函數(shù)返回 若成功則為子進程ID號 若出錯則為 1 Status選項 為空時 代表任意狀態(tài)結束的子進程 若不為空 則代表指定狀態(tài)結束的子進程 41 wait和waitpid函數(shù)的區(qū)別 在一個子進程終止前 wait使其調(diào)用者阻塞 而waitpid有一選擇項 可使調(diào)用者不阻塞 waitpid并不等待第一個終止的子進程 它有若干個選擇項 可以控制它所等待的特定進程 實際上wait函數(shù)是waitpid函數(shù)的一個特例 42 對于waitpid的pid參數(shù)的解釋與其值有關 pid 1等待任一子進程 于是在這一功能方面waitpid與wait等效 pid 0等待其進程ID與pid相等的子進程 pid 0等待其組ID等于調(diào)用進程的組ID的任一子進程 pid 1等待其組ID等于pid的絕對值的任一子進程 43 waitpid函數(shù)提供了wait函數(shù)沒有提供的三個功能 1 waitpid等待一個特定的進程 而wait則返回任一終止子進程的狀態(tài) 2 waitpid提供了一個wait的非阻塞版本 有時希望取得一個子進程的狀態(tài) 但不想阻塞 3 waitpid支持作業(yè)控制 以WUNTRACED選擇項 44 11 4linux多線程編程 Linux下線程概述linux線程實現(xiàn) 45 1 Linux下線程概述 進程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位 每個進程有自己的數(shù)據(jù)段 代碼段和堆棧段 線程通常叫做輕型的進程 線程是在共享內(nèi)存空間中并發(fā)執(zhí)行的多道執(zhí)行路徑 他們共享一個進程的資源 因為線程和進程比起來很小 所以相對來說 線程花費更少的CPU資源 46 1 Linux下線程概述 圖1進程與線程的關系 47 1 Linux下線程概述 線程按照其調(diào)度者可分為用戶級線程和內(nèi)核級線程兩種 1 用戶級線程主要解決的是上下文切換的問題 其調(diào)度算法和調(diào)度過程全部有用戶決定 2 內(nèi)核級線程有內(nèi)核調(diào)度機制實現(xiàn) 現(xiàn)在大多數(shù)操作系統(tǒng)都采用用戶級線程和內(nèi)核級線程并存的方法 用戶級線程可與內(nèi)核級線程實現(xiàn) 一對一 一對多 的對應關系 48 2 linux線程實現(xiàn) 以下線程均為用戶級線程 在linux中 一般采用Pthread線程庫實現(xiàn)線程的訪問與控制 由POSIX提出 具有良好的可移植性 49 2 1線程創(chuàng)建與退出 創(chuàng)建線程使用pthread create函數(shù) 在線程創(chuàng)建以后 就開始運行相關的線程函數(shù) 線程退出時使用函數(shù)pthread exit 是線程的主動行為 注意進程退出時使用exit函數(shù) 線程中用pthread exit替代exit 由于一個進程中的多個線程共享數(shù)據(jù)段 因此通常在線程退出后 退出線程所占用的資源并不會隨線程結束而釋放 所有需要pthread join函數(shù)來等待線程結束 類似于wait系統(tǒng)調(diào)用 50 創(chuàng)建線程 includepthread create pthread t thread pthread attr t attr void start routine void void arg thread 線程標識符attr 線程屬性設置start routine 線程函數(shù)起始地址arg 傳遞給start routine的參數(shù) 51 線程退出 includepthread exit void retval retval pthread exit調(diào)用者線程的返回值 可由其他函數(shù)和pthread join來檢測獲取 52 等待線程退出 includepthread join pthread t th void thread return th 等待線程的標識符thread return 用戶定義指針 用來存儲被等待線程的返回值線程實例見 thread c 53 2 2修改線程屬性 在thread creat函數(shù)中有設置線程屬性參數(shù) 這些屬性包括綁定屬性 分離屬性 堆棧地址 堆棧大小 優(yōu)先級 系統(tǒng)默認屬性為非綁定 非分離 缺省1M的堆棧 與父進程同樣級別的優(yōu)先級 線程實例見 pthread c 54 2 3mutex互斥鎖線程控制 mutex是一種簡單的加鎖的方法來控制對共享資源的訪問 在同一時刻只能有一個線程掌握某個互斥上的鎖 擁有上鎖狀態(tài)的線程能夠?qū)蚕碣Y源進行訪問 若其他線程希望上鎖一個已經(jīng)被上了互斥鎖的資源 則該線程掛起 直到上鎖的線程釋放互斥鎖為止 55 互斥鎖的操作主要包括以下幾個步驟 互斥鎖初始化 pthread mutex init互斥鎖上鎖 pthread mutex lock互斥鎖判斷上鎖 pthread mutex trylock互斥鎖解鎖 pthread mutex unlock消除互斥鎖 pthread mutex destroy 56 互斥鎖初始化 includeintpthread mutex init pthread mutex t mutex constpthread mutex attr t mutexattr Mutex 互斥鎖Mutexattr PTHREAD MUTEX INITIALIZER 創(chuàng)建快速互斥鎖PTHREAD RECURSIVE MUTEX INITIALIZER NP 創(chuàng)建遞歸互斥鎖PTHREAD REEORCHECK MUTEX INITIALIZER NP 創(chuàng)建檢錯互斥鎖 57 互斥鎖操作 includeintpthread mutex lock pthread mutex t mutex intpthread mutex trylock pthread mutex t mutex intpthread mutex unlock pthread mutex t mutex intpthread mutex destroy pthread mutex t mutex Mutex 互斥鎖返回值 成功0 錯誤 1 互斥鎖實例見 mutex c 58 2 4信號量線程控制 信號量也就是操作系統(tǒng)中所用到的PV操作 它廣泛用于進程或線程間的互斥與同步 PV操作是對整數(shù)計數(shù)器信號量sem的操作 一次P操作使sem減一 一次V操作使sem加一 用于互斥時 幾個進程 或線程 往往只設置一個信號量sem 用于同步時 往往設置多個信號量 并安排不同的值了來實現(xiàn)它們之間的順序執(zhí)行 59 60 61 11 5Linux網(wǎng)絡編程 TCP IP協(xié)議概述 略 網(wǎng)絡編程基礎 62 2 網(wǎng)絡編程基礎 1 socket概述2 地址及順序處理3 socket編程基礎 63 1 socket概述 1 socket定義 在Linux中的網(wǎng)絡編程是通過socket接口來進行的 人們常說的socket接口是一種特殊的I O 它也是一種文件描述符 每一個socket都用一個半相關描述 協(xié)議 本地地址 本地端口 來表示 一個完整的套接字則用一個相關描述 協(xié)議 本地地址 本地端口 遠程地址 遠程端口 socket也有一個類似于打開文件的函數(shù)調(diào)用 該函數(shù)返回一個整型的socket描述符 隨后的連接建立 數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^socket來實現(xiàn)的 64 1 socket概述 2 socket類型常見的socket有3種類型 1 流式socket SOCK STREAM 流式套接字提供可靠的 面向連接的通信流 它使用TCP協(xié)議 從而保證了數(shù)據(jù)傳輸?shù)恼_性和順序性 2 數(shù)據(jù)報socket SOCK DGRAM 數(shù)據(jù)報套接字定義了一種無連接的服務 數(shù)據(jù)通過相互獨立的報文進行傳輸 是無序的 并且不保證是可靠 無差錯的 它使用數(shù)據(jù)報協(xié)議UDP 3 原始socket原始套接字允許對底層協(xié)議如IP或ICMP進行直接訪問 它功能強大但使用較為不便 主要用于一些協(xié)議的開發(fā) 65 2 地址及順序處理 1 地址結構相關處理 Structsockaddr 保存著套接字的地址信息Structsockaddr Unsignedshortsa family 地址族Charsa data 14 套接字實際的地址數(shù)據(jù) 目的地址及端口 每種協(xié)議都有自己的網(wǎng)絡地址的定義 套接字API必須對這些不同的地址定義進行抽象 66 2 地址及順序處理 Internet通信域套接字地址結構sockaddr instructsockaddr in shortintsin family 地址族unsignedshortintsin port 端口號structin addrsin addr IP地址charsin zero 8 填充0以保持與structsockaddr同樣大小 這樣一個指向sockaddr in數(shù)據(jù)結構的指針可以強行轉(zhuǎn)換為一個指向數(shù)據(jù)結構sockaddr的指針 端口號以及Internet地址使用的是網(wǎng)絡字節(jié)順序 需要通過特殊函數(shù)進行轉(zhuǎn)換 67 2 地址及順序處理 結構字段 sa family字段可選的常見值 68 2 地址及順序處理 2 網(wǎng)絡字節(jié)順序 TCP IP網(wǎng)絡通常是異構的 它包含大量不同種類的計算機及體系結構 在體系結構上最大的區(qū)別就是存儲數(shù)據(jù)的方式 常見的方式有兩種 大尾端 把最高位的字節(jié)存放在最低的硬件地址上 和小尾端 反之 TCP IP協(xié)議使用大尾端 而所有的intel和intel兼容的處理器都采用小尾端字節(jié)存儲順序 因此在網(wǎng)絡上傳輸多字節(jié)數(shù)據(jù)的順序被稱為網(wǎng)絡字節(jié)順序 69 2 地址及順序處理 2 網(wǎng)絡字節(jié)順序 幾個字節(jié)順序轉(zhuǎn)換函數(shù) Htons HostToNetworkShort 主機地址 網(wǎng)絡字節(jié)順序Htonl HostToNetworkLong 主機地址 網(wǎng)絡字節(jié)順序 長型 此長型非C語言中的long 詳見函數(shù)原型 ntohs NetworkToHostShort 網(wǎng)絡字節(jié)順序 主機地址ntohl NetworkToHostlong 網(wǎng)絡字節(jié)順序 主機地址 長型 70 2 地址及順序處理 3 地址格式轉(zhuǎn)化 通常在表達地址時采用的是點分十進制表示的數(shù)值 或者是以冒號分開的十進制IPv6地址 而在通常使用的socket編程中所使用的則是二進制值 這就需要將這兩個數(shù)值進行轉(zhuǎn)換 這里在IPv4中用到的函數(shù)有inet aton inet addr和inet ntoa 而IPv4和IPv6兼容的函數(shù)有inet pton和inet ntop inet pton函數(shù)是將點分十進制地址映射為二進制地址 而inet ntop是將二進制地址映射為點分十進制地址 71 2 地址及順序處理 字符串的IP地址與32位的IP地址的轉(zhuǎn)換 72 2 地址及順序處理 4 名字地址轉(zhuǎn)化 通常 人們在使用過程中都不愿意記憶冗長的IP地址 尤其到IPv6時 地址長度多達128位 那時就更加不可能一次次記憶那么長的IP地址了 因此 使用主機名將會是很好的選擇 在Linux中 同樣有一些函數(shù)可以實現(xiàn)主機名和地址的轉(zhuǎn)化 最為常見的有gethostbyname gethostbyaddr getaddrinfo等 它們都可以實現(xiàn)IPv4和IPv6的地址和主機名之間的轉(zhuǎn)化 其中gethostbyname是將主機名轉(zhuǎn)化為IP地址 gethostbyaddr則是逆操作 是將IP地址轉(zhuǎn)化為主機名 另外getaddrinfo還能實現(xiàn)自動識別IPv4地址和IPv6地址 gethostbyname和gethostbyaddr都涉及到一個hostent的結構體 73 2 地址及順序處理 Structhostent char h name 正式主機名 char h aliases 主機別名 inth addrtype 地址類型 inth length 地址長度 char h addr list 指向IPv4或IPv6的地址指針數(shù)組 74 2 地址及順序處理 structaddrinfo intai flags AI PASSIVE AI CANONNAME intai family 地址族 intai socktype socket類型 intai protocol 協(xié)議類型 size tai addrlen 地址長度 char ai canoname 主機名 structsockaddr ai addr socket結構體 structaddrinfo ai next 下一個指針鏈表 75 2 地址及順序處理 getaddrinfo c include include include include include include include includeintmain structaddrinfohints res NULL intrc memset 設置addrinfo結構體中各參數(shù) hints ai family PF UNSPEC hints ai socktype SOCK DGRAM hints ai protocol IPPROTO UDP 調(diào)用getaddinfo函數(shù) rc getaddrinfo 127 0 0 1 123 getaddrinfo函數(shù)用法的示例 76 3 socket基礎編程 用戶進程 套接字接口 網(wǎng)絡協(xié)議 網(wǎng)絡設備 是進程與網(wǎng)絡協(xié)議之間的接口中 在Linux中socket屬于文件系統(tǒng)的一部分 網(wǎng)絡通信可以看成對文件的讀取 在一個通信連接中的兩端通信程序各自有一個套接字來描述自己那一端 77 3 socket基礎編程 套接字與文件描述字相同點 像文件描述字一樣 套接字也使用read write來讀寫數(shù)據(jù) 不同點 套接字除了有一個地址以外 還包含3個屬性 域 類型和協(xié)議 78 3 socket基礎編程 基于TCP 即面向連接的通信數(shù)據(jù)流 79 3 socket基礎編程 使用TCP協(xié)議socket編程流程圖 80 3 socket基礎編程 第一步 創(chuàng)建套接字以獲得文件描述符 include includeintsocket intdomain inttype intprotocol 函數(shù)說明 創(chuàng)建一個套接字描述符 如果失敗返回 1 domain為地址族AF XXX type為套接字類型 SOCK STREAM TCP SOCK DGRAM UDP SOCK RAW IP ICMP protocol指定協(xié)議0為自動選擇 81 3 socket基礎編程 include includeintbind intsockfd structsockaddr my addr intaddrlen 函數(shù)說明 成功返回0 如果失敗返回 1sockfd 由socket 調(diào)用返回的文件描述符myaddr 指向sockaddr的指針 由于系統(tǒng)兼容性問題 一般使用structsockaddr in代替 addrlen sockaddr結構的長度 第二步 建立連接 將套接字與本地計算機的地址綁定在一起 82 3 socket基礎編程 include include include defineMYPORT3333 最好選擇1024以后的端口Main Intsockfd Structsockaddr inmy addr 通常情況下使用sockaddr in結構Sockfd socket AF INET SOCKET STREAM 0 my addr sin family AF INET my addr sin port htons MYPORT 或者設置為零也可 內(nèi)核會自動分配一個未使用的端口My addr sin addr s addr inet addr 192 168 1 125 寫法二My addr sin addr s addr htonl INADDR ANY 非指定地址被包含在常量INADDR ANY中Bzero 將套接字與本地計算機的某個端口綁定在一起 示范如何使用bind 83 3 socket基礎編程 在套接字被綁定到地址后 進程通過調(diào)用listen 來告訴系統(tǒng)它愿意讓其它進程與該套接字建立連接 intlisten intsockfd intbacklog sockfd bind 后的文件描述符 Backlog 等待聯(lián)機隊列的大小 等待中而未被accept 的聯(lián)機請求被放在隊列 當隊列滿了就無法再接受聯(lián)機請求 client會收到connectionrefused的錯誤 執(zhí)行成功返回0 失敗為 1 第三步 等待client聯(lián)機請求 84 3 socket基礎編程 intaccept intsockfd structsockaddr addr int addrlen Sockfd 是listen后的文件描述符Addr 將被client的ipaddress填充Addrlen 將被client的ipaddress的長度填充成功則返回client的socket文件描述符 之后的數(shù)據(jù)傳輸就可以使用新的文件描述符 第四步 接受client聯(lián)機請求 連接并不是立即建立進來的 必須通過accept 系統(tǒng)調(diào)用接收連接請求 新的試圖連接到已監(jiān)聽地址的連接請求稱為未決的連接 這個連接一直等待直到被accept 為止 85 3 socket基礎編程 客戶端步驟 intconnect intsockfd structsockaddr serv addr intaddrlen sockfd socket返回的文件描述符serv addr 指向structsockaddr的指針 保存服務器端的連接信息Addren 可以用sizeof structsockaddr 設置成功返回0 出錯則返回 1 第一步與server端程序相同 第二步可直接使用connect與服務器連接 86 3 socket基礎編程 Send 和recv 函數(shù) includeintsend intsockfd constvoid msg intlen intflags Sockfd 希望進行數(shù)據(jù)傳遞的套接字的文件描述符Msg 指向發(fā)送數(shù)據(jù)的指針Len 希望發(fā)送的數(shù)據(jù)的字節(jié)長度Flags 通常設置為0成開則返回實際發(fā)送字節(jié)的長度 出錯則返回 1 intrecv intsockfd void buf intlen unsignedintflags Buf 保存讀入信息的地址Len 表示接收buf的最大長度 87 3 socket基礎編程 可以使用close intsockfd 和shutdown intsock inthow 來關閉連接的套接字文件描述符 Shutdown中的how參數(shù)含義如下 0 代表斷開遠程接收1 代表斷開遠程發(fā)送2 代表斷開遠程接收和發(fā)送 88 listenfd socket bind listenfd listen listenfd while 1 connfd accept listenfd n fork if n 1 perror calltofork exit 1 elseif n 0 close listenfd while 1 read connfd write connfd close connfd exit 0 elseclose connfd 使用fork并發(fā)處理多個client的請求 89 3 socket基礎編程 基于UDP的c s模式 90 3 socket基礎編程 使用UDP協(xié)議socket編程流程圖 91 用于無連接發(fā)送與接收數(shù)據(jù)的系統(tǒng)調(diào)用 用于數(shù)據(jù)報套接字 Sendto 和recvfrom 函數(shù) includeintsendto intsockfd constvoid msg intlen unsignedintflags Conststructsockaddr to inttolen 除最后兩個參數(shù)之外 其它參數(shù)與send 相同 to指向包含目的IP地址和端口號的數(shù)據(jù)結構sockaddr的指針 tolen可以設置為Sizeof structsockaddr intrecvfrom intsockfd void buf intlen unsignedintflags Structsockaddr from int fromlen From 指向本地計算機中包含源IP地址和端口號的數(shù)據(jù)結構Sockaddr的指針 fromlen可以設置為sizeof structsockaddr 如果對源地址不感興趣 可以設置為NULL 92 11 5Linux庫 Linux庫概述庫操作工具靜態(tài)庫共享庫動態(tài)鏈接庫 93 一 Linux庫概述 庫的概念 庫是操作系統(tǒng)或者編譯器提供的一種目標文件 是可以被多個軟件項目使用的二進制代碼集 庫是代碼重用思想的體現(xiàn) 使用庫可以節(jié)約編程人員大量的時間 94 庫分類 靜態(tài)庫 是在執(zhí)行程序運行前就已經(jīng)加入到執(zhí)行碼中 在物理上成為執(zhí)行程序的一部分 共享庫 是在執(zhí)行程序啟動時加載到執(zhí)行程序中 可以被多個執(zhí)行程序共享使用 動態(tài)鏈接庫 其實并不是一種真正的庫類型 應該是一種庫的使用技術 應用程序可以在運行過程中隨時加載和使用庫 95 庫命名約定 所有庫都以lib開頭 表示一個庫文件 文件名以 a結尾的是靜態(tài)庫 以 so結尾的是共享庫 96 共享庫庫名稱約定 共享庫命名規(guī)則稍顯繁瑣 我們來區(qū)分一下一下命名 realname 包含庫名 主版本號 次版本號以及發(fā)布號等字段 它代表文件中包含了庫的代碼 這是庫的實體文件 soname sharedobjectname 庫文件的一個符號鏈接 一般僅包括庫名和主版本號 linkername 庫文件的符號鏈接 它僅包含庫名 一般供編譯器使用 97 共享庫庫名稱約定 續(xù) 看下面的例子 在以上信息中 libpng so 2 1 0 12是共享庫的實名 realname libpng so 2是共享庫so名 soname libpng so則是連接名 linkername 用于編譯連接 ls l png lrwxrwxrwx1rootrootlibpng so libpng12 solrwxrwxrwx1rootrootlibpng so 2 libpng so 2 1 0 12 rw r r 1rootrootlibpng so 2 1 0 12 98 常用庫 庫頭文件描述libc so無標準C庫libdb sodb h數(shù)據(jù)庫庫libm somath h數(shù)學庫libpthread sopthread h多線程庫libz sozlib h壓縮例程庫libvga sovga h底層圖形庫libcom err socom err h出錯處理庫libdl sodlfcn h動態(tài)加載庫 99 二 庫操作工具 Linux系統(tǒng)提供很多對庫進行操作的工具 具體如下 nm命令ar命令ldd命令ldconfig命令 100 1 nm命令 用途 列出庫或目標文件的所有符號 查看程序調(diào)用什么函數(shù)查看一個給定的庫或者目標文件是否提供了所需的函數(shù) 舉例 下圖列出了libc so 6中所有包含sprintf的字符串的符號 101 nm命令 續(xù) 102 2 ar命令 用途 可以建立一個歸檔文件 通常用來創(chuàng)建靜態(tài)庫 舉例 建立靜態(tài)庫 arrclibmy afile1 ofile2 o 103 3 ldd命令 用途 列出為程序正常運行所需要的共享庫 舉例 利用ldd命令查看bash所依賴的庫文件 如下圖所示 104 ldd命令 續(xù) 105 4 ldconfig命令 當為系統(tǒng)安裝好庫文件之后 需要運行l(wèi)dconfig命令 其功能是根據(jù) etc ld so conf中的路徑檢查庫文件 并為它們創(chuàng)建相應的soname 然后更改ld so cache文件 106 ldconfig命令 續(xù) 應用程序執(zhí)行時 lib目錄下的程序ld linux so X X是版本號 會首先被運行 這就是Linux系統(tǒng)的程序裝載器 裝載器負責檢查應用程序需要使用的共享庫 從ld so conf指定的目錄中找到這些庫并加載 然后把加載信息寫入緩存文件 lib ld conf cache中供其他程序使用 以提高系統(tǒng)運行效率 107 ldconfig命令 續(xù) Linux系統(tǒng)下的一個環(huán)境變量 LD LIBRARY PATH 是一個由冒號分隔的目錄清單 包含了運行時的共享庫 可以指示ld so到何處搜索沒有保存在標準位置的庫 對應文件為 etc ld so conf 108 三 靜態(tài)庫 靜態(tài)庫一般命名為libxxx a 采用靜態(tài)編譯得到的程序文件比較大 因為整個函數(shù)庫都已經(jīng)被鏈接到程序中 靜態(tài)庫實質(zhì)是目標文件的集合 采用ar命令可以創(chuàng)建靜態(tài)庫 首先編寫源文件 然后把源文件分別編譯為目標文件 注意使用 c選項 然后用ar命令把目標文件歸檔為一個靜態(tài)庫文件 109 例 ch6 1main c voidhello voidbye includeintmain hello bye return0 靜態(tài)庫源文件 110 例 續(xù) ch6 1hello c includevoidhello printf helloeverybody n ch6 1bye c includevoidbye printf goodbye n 靜態(tài)庫源文件 111 例 續(xù) 112 四 共享庫 共享庫一般命名為libxxx so 與靜態(tài)庫不同 共享庫并不會在程序編譯時被添加到可執(zhí)行文件中 而是在程序執(zhí)行時才會被鏈接 因此采用動態(tài)編譯方式得到的可執(zhí)行程序文件比較小 但是程序的執(zhí)行依賴于環(huán)境 當前操作系統(tǒng)中必須存在程序需要的共享庫 否則程序不能執(zhí)行 編譯共享庫時要用gcc的 shared和 fPIC選項 前者表示編譯為共享庫 后者表示把庫文件編譯成位置無關代碼 否則將來程序無法運行 113 共享庫的生成和使用方法 114 共享庫 續(xù) 用ldd命令檢查main程序運行時所需要的動態(tài)庫 結果如下圖所示 115 庫依賴關系 116 五 動態(tài)鏈接庫 打開共享庫提取函數(shù)地址關閉共享庫共享庫錯誤函數(shù) 117 1 打開共享庫 函數(shù)原型 void dlopen constchar libname intflag 功能描述 將libname代表的庫裝載到內(nèi)存 flag是打開共享庫的方式 如果函數(shù)調(diào)用成功 返回庫句柄 如果該庫已經(jīng)被裝載過 則返回同樣的句柄 如果調(diào)用失敗 返回NULL 如果要裝載的庫依賴其他庫 必須先裝載依賴庫 118 打開共享庫 續(xù) 功能描述 參數(shù)中的libname一般是庫的絕對路徑 這樣dlopen會直接裝載該文件 如果只是指定了庫名稱 在dlopen會按照下面的機制去搜尋 根據(jù)環(huán)境變量LD LIBRARY PATH查找 根據(jù) etc ld so cache查找 依次在 lib和 usr lib目錄查找 flag參數(shù)表示處理未定義函數(shù)的方式RTLD LAZY 暫時不去處理未定義函數(shù) 先把庫裝載到內(nèi)存 等用到?jīng)]定義的函數(shù)再報錯RTLD NOW 馬上檢查是否存在未定義的函數(shù) 若存在 則dlopen以失敗告終 RTLD GLOBL 使共享庫定義的符號全局可見 119 2 提取函數(shù)地址 函數(shù)原型 void dlsym void handle char symbol 功能描述 在dlopen之后 庫被裝載到內(nèi)存 dlsym可以獲得指定函數(shù) symbol 在內(nèi)存中的位置 指針 如果找不到指定函數(shù) 則dlsym會返回NULL值 根據(jù)動態(tài)鏈接庫操作句柄 handle 與符號 symbol 返回符號對應的函數(shù)的執(zhí)行代碼地址 120 3 關閉共享庫 函數(shù)原型為 intdlclose void handle 功能描述 將已經(jīng)裝載的庫句柄減一 如果句柄減至零 則該庫會被卸載 121 4 共享庫錯誤函數(shù) 函數(shù)原型 constchar dlerror void 功能描述 當動態(tài)鏈接庫操作函數(shù) dlopen dlsym dlclose 執(zhí)行失敗時 dlerror可以返回出錯信息 返回值為NULL時表示操作函數(shù)執(zhí)行成功 122 例 源文件 ch6 2sub h ifndefSUB H defineSUB Hintsquare int endif ch6 2sub c includeintsquare inta printf thesquareofthenumberis returna a 123 ch6 2main c include include include include sub h intmain void handle int fp int char error intn intresult printf pleaseinputanumber n scanf d 例 續(xù) 聲明函數(shù)指針 將來用來執(zhí)行希望使用的函數(shù) 124 handle dlopen lib libmydll so RTLD LAZY if handle printf s n dlerror fp dlsym handle square if error dlerror NULL printf s n error dlclose handle exit 1 printf nowcallthefunctionsquare n result fp n printf d n result dlclose handle return0 打開動態(tài)鏈接庫RTLD LAZY 只有在使用時才檢查錯誤 125 handle dlopen lib libmydll so RTLD LAZY if handle printf s n dlerror fp dlsym handle square if error dlerror NULL printf s n error dlclose handle exit 1 printf nowcallthefunctionsquare n result fp n printf d n result dlclose handle return0 如未成功 handle為NULL 則顯示錯誤信息 126 handle dlopen lib libmydll so RTLD LAZY if handle printf s n dlerror fp dlsym handle square if error dlerror NULL printf s n error dlclose handle exit 1 printf nowcallthefunctionsquare n result fp n printf d n result dlclose handle return0 找到需要的函數(shù) 127 handle dlopen lib libmydll so RTLD LAZY if handle printf s n dlerror fp dlsym handle square if error dlerror NULL printf s n error dlclose handle exit 1 printf nowcallthefunctionsquare n result fp
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 網(wǎng)絡管理員基礎培訓課程
- 中班健康:認識肚臍
- 工程公司內(nèi)部培訓
- 10kv配網(wǎng)帶電作業(yè)培訓
- 園長培訓:如何應對幼兒分離焦慮
- 無人機輔助車隊運輸合同范本
- 跨國車輛損傷賠償及國際物流合同
- 文化創(chuàng)意步行街個人店鋪租賃與創(chuàng)意產(chǎn)業(yè)發(fā)展合同
- 互聯(lián)網(wǎng)企業(yè)財務人員客戶信息保密責任合同
- 餐飲企業(yè)品牌推廣合作經(jīng)營協(xié)議
- 溫州市2024-2025學年高一下學期6月期末-英語試卷及答案
- 專利代理所管理制度
- 2025至2030年中國核電材料行業(yè)市場現(xiàn)狀分析及發(fā)展戰(zhàn)略研判報告
- 玄隱遺密(含黃帝內(nèi)經(jīng))
- 2025至2030年中國高鎳三元材料產(chǎn)業(yè)發(fā)展動態(tài)及投資方向分析報告
- DB13T 1320.10-2010 中藥材種子質(zhì)量標準 第10部分:防風
- (2025春新版本)人教版七年級生物下冊全冊教案
- 醫(yī)院殘疾評定管理制度
- 雜志分揀打包服務合同4篇
- 2025年D-對羥基苯甘氨酸項目市場調(diào)查研究報告
- 2024-2025 學年八年級英語下學期期末模擬卷 (常州專用)解析卷
評論
0/150
提交評論