linux學習筆記

1 Linux第一天====================================================================================node

   2 一.基礎命令linux

   3 1.history 查看歷史命令,此終端自安裝至如今的全部。git

   4 2.命令解析器:算法

   5     1)shell. 針對Unix操做系統shell

   6     2)bash.  針對Linux操做系統數據庫

   7     3)工做方式: 用戶在終端輸入命令, 命令解析器搜索(經過環境變量中的路徑)對應的路徑,查找同名命令,若是找到了就執行該命令。編程

   8ubuntu

   9 3.遍歷歷史命令:windows

  10     1)從當前位置往上: ctrl+p(方向鍵上也行);設計模式

  11     2)從當前位置向下: ctrl+n(方向鍵下也行);

  12

  13 4.光標移動:

  14     1)向前 ctrl+b;  2)向後 ctrl+f;  3)移動到行首 ctrl+a;  4)移動到行首 ctrl+e;

  15

  16 5.刪除光標位置的字符:

  17     1)光標後面的字符(即光標蓋住的那個字符):ctrl+d;

  18     2) 光標前面的字符:ctrl+h;

  19     3) 刪除光標前面的字符串: ctrl+u;

  20     4) 刪除光標後面的字符串:ctrl+k;

  21

  22 二.Linux目錄結構:

  23 1. / 根目錄:根目錄下面的是系統文件,通常別動。

  24 2. 終端下面的各類顏色表明不一樣的文件

  25     1).白色: 普通文件

  26     2)藍色: 目錄

  27     3)綠色: 可執行文件

  28     4)青色: 連接文件

  29     5)紅色: 壓縮文件

  30     6)黃色: 設備文件

  31     7)灰色: 其餘文件

  32

  33 3.根目錄下面各文件的內容:

  34     1)bin: (binary)二進制文件,存放命令(系統命令,可執行的程序)

  35    

  36     2)etc: 系統或用戶安裝的軟件用到的"配置文件";

  37         如:查看用戶:etc/passwd (能夠看到當前系統下的全部用戶)用戶登陸時的用戶名和密碼也在該目錄

  38    

  39     3) lib: Linux操做系統運行時使用的一些基本動態庫(.so)。

  40    

  41     4)media:自動掛載外設,會將外設自動掛載到該目錄下。

  42    

  43     5)mnt: 手動掛載目錄。通常默認掛載到該目錄。

  44    

  45     6)opt: 安裝目錄,通常是空的。

  46    

  47     7)root: 超級用戶的家目錄

  48    

  49     8)sbin: 超級用戶運行時用到的命令(存放的地方)   

  50     9)usr(user software resource): 用戶軟件資源目錄;(1.當前用戶安裝的一些應用程序,2.一些庫文件(如C 的標準庫))。    

  51     10)boot: 開機啓動項

  52     11) dev: 存放設備文件

  53     12)home: Linux操做系統全部用戶的家目錄。

  54     13)tmp: 存放臨時文件(每次系統從新啓動,都會清空)

  55    

  56 4.yyx@yyx-virtual-machine:/home$: 字符的意義

  57     1)$:表示普通用戶;  #:表示超級用戶

  58     2)@前的內容: 表示當前用戶名;

  59     3)@後的內容,在冒號以前: 表示主機名。

  60     4)冒號後的內容: 表示當前所在的目錄。

  61

  62 5.系統安裝程序後綴

  63   ubuntu  系統安裝程序後綴:.deb

  64   windows 系統安裝程序後綴:.exe

  65   安卓      系統安裝程序後綴:.gdb

  66

  67 6.Linux 七種文件類型

  68     1) d: 目錄

  69     2)    -: 普通文件

  70     3) c: 字符設備

  71     4) b: 塊設備

  72     5) p: 管道

  73     6) s: 套接字(實現局域網的傳輸 sorckt)

  74     7) l:符號連接

  75

  76     在細分爲:

  77         d, -, l;  (佔用內存空間)

  78     僞文件:(不佔用內存空間)

  79         c, b, p, s;

  80 7.建立文件:

  81     1)touch 文件; 文件存在,就會更新文件的日期;

  82                     文件不存在,就會建立文件。

  83

  84 8.建立嵌套目錄:

  85     mkdir wbq/aa/bb    -p;(注意後面的參數-p,能夠加在最後面,也能夠加在緊隨mkdir後面)    bb目錄在aa目錄裏,aa在wbq目錄裏。

  86     pwd 查看當前用戶所在的目錄。

  87

  88

  89 8.查看文件內容:

  90     1)cat+文件名:  文件內容顯示在終端上

  91     2)more+ 文件名:只能向下翻。回車向下走一行,空格,顯示下一頁。

  92     3)less+ 文件名: 能夠上下翻頁

  93     4)head -行數 文件名(從文件頭部數)

  94     5)tail -行數 文件名(從文件尾部數)

  95

  96 9.拷貝文件/目錄

  97     cp 存在的文件 新文件(當拷貝文件時,須要有"讀權限").

  98         1)若是新文件名不存在,就建立

  99         2)若是新文件名存在,就覆蓋源文件(這裏要注意,新文件名通常要寫成不存在的,不然原來的內容就丟了)

 100     cp拷貝目錄

 101         須要加參數 "-r";

 102

 103 10.建立軟硬連接

 104     1)建立軟鏈接:

 105         ln -s 建立軟鏈接的源文件名  軟連接名字

 106             1)使用相對路徑建立的軟鏈接,移動連接到不一樣的目錄就不可使用了。

 107             2)解決這種問題辦法: 建立絕對路徑的軟鏈接。在原文件名前加上它的絕對路徑。

 108     2)建立硬連接:

 109         ln 建立硬連接的源文件名  硬連接名字

 110             1)硬連接的文件不區分相對和絕對路徑。

 111             2)硬連接文件不佔用磁盤空間,一改全改(無論哪一個,至關於程序的靜態變量)

 112

 113 11.修改文件權限的方法(chmod)

 114     1)文字法 (r w x ) chmod 修改對象+(-)權限 文件名

 115         u 用戶        g 用戶組       o其餘人        a全部人

 116

 117     2)數字設定法: chmod 數字    文件名

 118         寫權限 對應的數字      2

 119         讀權限 對應的數字     4

 120         執行權限 對應的數子 1

 121

 122 12.修改文件全部者(chown)   

 123     1)修改文件的所屬者:  chown 全部者 文件名(要使用超級用戶權限)

 124     2)修改文件的所屬組      chown  全部者:所屬組  文件名

 125     3)修改文件所屬組(第二種方法): sudo chgrp 所屬組 文件名;

 126

 127 13.文件的查找和檢索

 128     1)根據文件的屬性查找 find

 129         1)根據文件名  find 查找的路徑 -name "查找的文件名"

 130

 131         2)根據文件大小    find 查找的路徑 -size 查找的大小

 132             大於:+; 小於:-;  等於:(不用寫)

 133             如: find ~ -size +100k -size -100M    (查找大於100k小於100M的文件)

 134             注意: k 小寫  M大寫

 135             "~ 當前用戶的家目錄(或者宿主目錄)"

 136

 137         3)根據文件類型:find 查找的路徑 -type 文件類型

 138

 139     2)根據文件內容查找 grep

 140         1)grep -r "查找的內容" 查找的路徑(能夠和一些命令搭配):find ./ -type f | grep 01.c;  "查找當前目錄下,名字含有01.c的普通文件"

 141

 142     3)locate 文件名;這個命令更快。直接搜索linux數據庫,有索引,因此很快。

 143         可是缺點:若是數據庫沒有更新,會有內容找不到。不關機的狀況下,linux默認天天半夜兩點左右更新。

 144

 145 14.查看文件或目錄屬性       

 146     1)查看文件文件的字節數,字數, 行數; wc 文件名 參數

 147     2)參數:-c:  文件的字符數

 148              -l:  文件的行數(也能夠用來喝一些命令搭配); find ./ -type f | wc -l;  "查找當前目錄下,普通文件的個數"。

 149              -w:  文件的字節數。   

 150

 151 15.查看指定命令所在的路徑:

 152      which  命令;能夠查看該命令所在的文件。(cd命令例外, 它被嵌入在系統中)

 153

 154 16.軟件的安裝和卸載:

 155     1.

 156         1)主流安裝(在線):

 157             1)sudo apt-get install 軟件名    :  安裝

 158         2)主流卸載:

 159             1)sudo apt-get remove  軟件名    :  卸載

 160         3)更新軟件列表

 161             1)sudo apt-get update ; (它的工做原理是:更新軟件的下載地址。)更新完後再從新下載

 162         4)清空緩存:

 163             1) sudo apt-get clean ;    清空在線安裝後的緩存

 164                 緩存的路徑:

 165

 166     2.

 167            5)安裝包程序安裝:.deb後綴(安裝包的名字)

 168

 169         6)安裝包安裝的軟件卸載:

 170

 171 17. U 盤的掛載和卸載

 172     1)掛載: mount 命令

 173         1)mount + 設備名 + 掛載的目錄

 174         2)獲取U盤設備名:

 175             sudo fdisk -l;

 176         3)顯示中文:

 177             加上參數: -o iocharset utf8

 178

 179 18:  sd 閃盤(U盤)

 180      hd 移動硬盤

 181      fd 軟盤;

 182

 183 19.壓縮包管理(Linux):

 184     1) 壓縮格式:    "(只壓縮不打包)"

 185         .gz格式:

 186             壓縮:   gzip 壓縮的文件;

 187             缺點:   1. 壓縮不保留原文件, 2.壓縮的時候不能能打包。  3.不能壓縮目錄

 188             解壓縮:     gunzip 壓縮包名

 189

 190         .bz2格式:

 191             壓縮:   bzip2    壓縮的文件;(若是想保留源文件;加參數 -k;  bzip2 壓縮的文件 -k )

 192             解壓縮: bunzip2  壓縮包名;

 193             缺點: 1.壓縮的時候不能打包,  2.不能壓縮目錄

 194

 195     2)經常使用的壓縮工具:"(只打包不壓縮)"

 196          1)tar:打包。

 197             參數:j- (指定的壓縮工具)

 198                   z- (指定的壓縮工具)

 199                   c-  建立新的壓縮文件

 200                   x-  從壓縮文件中釋放文件   

 201                   v-  詳細報告壓縮文件信息

 202                   f-  指定壓縮文件的名字

 203

 204         2)壓縮語法:

 205             tar 參數 壓縮包名稱 原材料(參數,與壓縮工具配合;zc. jc. )

 206                 1)zcvf

 207                 tar zcvf test.tar.gz 須要壓縮的文件

 208                 2) jcvf

 209                 tar jcvf test.tar.bz2 須要壓縮的文件

 210

 211         3)解壓縮:

 212             tar 參數 壓縮包名

 213                 語法:

 214                     .tar.gz後綴的壓縮文件    tar zxvf test.tar.gz

 215                     .tar.bz2後綴的壓縮文件  tar jxvf test.tar.bz2

 216

 217             解壓縮到指定目錄:

 218             (參數)    -C 指定的目錄(路徑)。

 219                     tar zxvf test.tar.gz  -C 路徑

 220                     tar jxvf test.tar.bz2 -C 路徑

 221

 222     3) 非主流的壓縮文件:rar

 223         1)安裝軟件: rar  (sudo apt-get install rar)

 224        

 225         2)壓縮:

 226             1)rar a 壓縮包名 原材料; (壓縮包的名字不須要添加後綴)

 227                 rar a test  須要壓縮的文件

 228             2)-r 參數(壓縮目錄): rar a test 須要壓縮的文件 -r;

 229        

 230         3)解壓縮:rar x 壓縮包名

 231             rar x test.rar (知道那個的目錄,可加可不加);

 232

 233     4)zip

 234         1)壓縮:

 235             壓縮目錄(加參數 -r);(zip (-r) 壓縮包名 原材料);包名不須要後綴

 236             zip test 須要壓縮的文件;  zip -r test 須要壓縮的目錄 ;

 237         2)解壓縮:

 238             unzip 壓縮包名 (-d) 解壓縮的目錄(路徑)

 239             unzip test.zip (解壓在當前目錄);   unzip test.zip -d 指定的目錄

 240

 241 4)-的使用時機:

 242

 243 20.進程管理:

 244     1) who 當前登陸操做系統的用戶和終端設備編號

 245     2) tty

 246     3)  PID 進程的ID號。

 247     查看整個系統 的運行情況:ps

 248     4) ps aux | grep 查找的東西

 249     5)

 250

 251 21.手動殺死進程

 252     1)kill -9(SIGKILL) 進程PID;

 253     2)查看kill的信號: kill -l;

 254

 255 22.查看環境變量:env

 256     1)環境變量的格式:key = value:value:value:……;

 257

 258 23.任務管理器: top

 259     1)關閉它: q 或者 ctrl +

 260

 261 24.網絡管理:

 262     1)獲取網絡接口的信息:ifconfig

 263     2)測試與其餘主機的連通性

 264         參數

 265

 266     3)

 267

 268 三。用戶管理

 269     1.添加用戶:

 270         1) sudo adduser

 271     2.添加用戶組

 272

 273     vi etc/passwd;       vi etc/group;

 274

 275     3.切換用戶:su; sudo su;這兩個操做的區別

 276         1)普通用戶

 277         2)超級用戶

 278     4.修改用戶密碼:

 279         1.修改普通用戶的密碼

 280         sudo passwd 用戶名

 281         2.修改超級用戶的密碼

 282        

 283     5.刪除用戶

 284         sudo deluser 用戶名

 285     6.刪除組:

 286    

 287     7.退出:

 288

 289     命令:動詞在後面

 290     腳本:動詞在前面

 291

 292 四。經常使用服務器搭建:

 293     1.FTP服務器的搭建:

 294         1)它是:一款軟件;用戶來上傳和下載文件。

 295         2)服務器端:

 296             a.安裝軟件:sudo

 297             b.服務器端須要設置:

 298

 299         3)從新啓動服務,使配置生效

 300             sudo

 301

 302         4)客戶端的操做

 303             1.實名用戶登陸:

 304

 305             2.上傳個下載文件(注意:只能操做文件,不能操做目錄)

 306

 307                 1)缺點:

 308                     1)須要告訴對方服務器密碼;

 309                     2)用戶能夠在服務器任意目錄切換

 310

 311             3.匿名用戶登陸:       

 312                 必須指定匿名用戶登陸目錄

 313

 314 五:lftp客戶端的使用

 315     1.只是一個登陸ftp 服務器的客戶端

 316     2.使用前先安裝: sudo apt-get install lftp

 317     3.登陸ftp服務器

 318         1.lftp IP(服務器的IP);

 319         2.login --- 匿名用戶登陸

 320

 321     4.基本操做:

 322     基本操做:    put, get;(與自帶的ftp功能同樣)  。

 323     上傳多個文件: mput 文件名;

 324     下載多個文件: mget 文件名

 325     下載目錄: mirror 目錄名;

 326     上傳目錄: mirror -R 目錄名;

 327

 328 六: 查看掩碼:命令 umask ;

 329         它的做用: 本地的掩碼: 0002;本地建立的目錄權限爲 775; 滿權限爲 777; 能夠看出實際權限 = 滿權限-掩碼

 330                                       本地建立的文件的權限爲 664; 本地的目錄權限 - 文件權限 = 111; 能夠看出:文件默認不會給它執行權限。

 331

 332         "目錄必須有執行權限才能被打開。"

 333         ftp上傳的文件默認權限爲 700; 此時只有 ftp 用戶能夠操做,不合理;須要修改配置文件;anoy_umask=022; 這樣ftp用戶傳輸到服務器的文件權限就爲 755了;

 334         目錄權限與掩碼的關係: 目錄權限 = 777 - 掩碼;

 335         文件權限與掩碼的關係: 文件權限 = 777 - 掩碼 - 111;

 336

 337 七:nfs網絡共享服務器的搭建和使用

 338     1.nfs ===至關於windows的共享目錄

 339     2.服務器端:

 340         1.安裝服務器程序:sudo apt-get install nfs-kernel-server;

 341         2.建立一個共享目錄:

 342             1)設置配置文件: /etc/exports;  添加一個共享的目錄(絕對路徑)和 ip 地址段和(權限);

 343             2)權限: ro ----只讀;    rw ----讀寫;             sync -----數據實時同步

 344             例如: /home/yyx/xuexi 192.168.22.*(rw,sync) 這個ip地址爲:容許這個網段的用戶掛載共享路徑。

 345         3.重啓服務:  sudo service nfs-kernel-server restart;

 346

 347     3.客戶端:

 348         1.經過掛載服務器共享目錄的方式:

 349             sudo mount serverIP(服務器的Ip):共享的路徑 掛載的路徑;

 350         2.退出方式:

 351             與普通掛載同樣。sudo umount 掛載的路徑

 352

 353 八。ssh服務器的使用:(管理員纔會使用)。

 354     1.做用: 遠程登陸程序;

 355     2.軟件的安裝: sudo apt-get install openssh-server;

 356     3.遠程登錄:

 357         ssh 用戶名@IP(要遠程登陸的用戶名和它的IP)

 358     4.退出:logout。

 359

 360 九。超級拷貝

 361 scp命令: 安裝軟件:sudo apt-get install openssh-server

 362     命令: scp-r (遠程服務器用戶名@IP(遠程):遠程服務器的目錄  拷貝到的本地目錄)

 363         scp -r Robin@192.168.28.37:/home/Robin/share ~/test

 364

 365

 366 "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————"

 367 FTP 服務器搭建和登陸

 368 1.先安裝服務器: 命令: sudo apt-get install vsftpd

 369 2.修改配置文件: 命令:sudo vi /etc/vsftpd.conf;

 370 3.重啓ftp服務: 命令: sudo service vsftpd restart;

 371 4.此時只容許實名用戶登陸和操做,匿名用戶只能登陸。

 372 5.匿名用戶登錄設置:建立一個專屬匿名用戶根目錄。

 373     1)修改配置文件:添上專屬根目錄

 374     2)重啓ftp服務器

 375 6.此時就均可以登陸和使用了

 376 7.用戶登陸:ftp IP(服務器的IP);

 377     1)匿名用戶登陸:用戶名:anonymous;  密碼:不須要

 378 8.傳輸數據: put;  下載數據: get;

 379 9.弊端:只能操做文件,不能操做目錄。

 380 "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————"

 381

 382 "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————"

 383 lftp 客戶端的使用;

 384

 385 "——————————————————————————————————————————————————————————————————————————————————————————————————————————————————"

 386

 387 十。 VI 的三種模式:

 388     1. 命令模式:

 389         h左 j下 k上 l下(左右在兩端,上下在中間);

 390     2. 文本模式:

 391     3. 末行模式:

 392

 393     4.一些基本操做:

 394         1.光標移動到文件開頭: gg;  光標移動到文件尾部: G;

 395         2.光標移動到行首:0; 光標移動到行尾: $;

 396         3.行跳轉【如: 13行】: 13G;

 397         4.刪除光標後的字:x; 刪除光標前的一個字: X; 刪除一個單詞: dw;

 398         5.刪除光標前本行的內容:d0; 刪除光標後本行的內容: D;

 399         6.刪除光標所在行: dd;   刪除多行:  行數 + dd;

 400         7.撤銷: u;  反撤銷: ctr + r;

 401         8.複製:複製當前行:yy;  複製從當前行如下 n 行: n yy; 

 402         9.粘貼: 從光標所在位置下一行粘貼: p;  從光標當前行位置粘貼: P;

 403

 404     5.可視模式:

 405         命令: v;    進入模式後,能夠有選擇的拷貝和刪除(如只拷貝一行中的某些內容)

 406

 407     6.查找操做:

 408         從光標位置向上查找:?+查找的內容;  從光標位置向下查找:/ + 查找的內容; n ----遍歷操做

 409         查光標所在位置的內容: 命令 #;

 410     7.替換操做: 單字符替換:命令 r(再輸入本身想輸入的內容。)替換光標後的字符;

 411

 412     8.建立新行:命令 o:當前光標所在行的下面;   命令 O:相反。

 413       刪除光標當前行:S,而後進入文本模式;   刪除光標前一個字符:s,而後進入文本模式;

 414

 415     9.末行模式下的替換:

 416         1)先在命令模式下進行查找操做,而後在末行模式下替換。

 417         2):s/查找的內容/替換的內容;

 418

 419     10.分屏操做:

 420         水平分屏:sp+文件名 ;    垂直分屏:vsp+文件名 ;     屏幕切換:ctr + ww;

 421

 422     11.打日誌: -D, -I; -g;  -Wall;  -O優化等級

 423

 424

 425 "----------------------------------------------------------------------------------"

 426     12.生成靜態庫:

 427         1.命名格式:libxxx.a

 428         2.製做:

 429             1)生成 .o文件;gcc -c .c文件 -I(.c文件中使用的)頭文件所在路徑(本身編寫的頭文件);

 430                 如:"gcc -c *.c -I ../include;"

 431                

 432             2)將生成的.o文件打包; ar rcs 靜態庫的名字 全部的.o文件

 433                     例如: "ar rcs libCalc.a *.o;"

 434

 435                     查看打包後的靜態庫: nm 名字;

 436                            "nm libCalc.a;"

 437

 438         3.靜態庫的使用:"(-I 後面的路徑能夠加空格(版本高的,可加可不加),能夠不加(版本低的))"

 439             1)第一種方法;   gcc + 測試.c文件 -o 可執行程序的名稱  -I頭文件的路徑 靜態庫的路徑

 440               例如:gcc main.c -o app -I ./include lib/libcacal.a;

 441                2)第二種方法: gcc + 測試文件 -o 可執行程序名稱 -I 頭文件的路徑 -L 靜態庫的路徑 -l xxx(靜態庫的名字,掐頭去尾(去掉lib 和 .a));

 442                例如:gcc main.c -o app1 -I ./include -

 443                L ./lib -l cacal;

 444         4.靜態庫的優缺點:

 445             優勢:  1)庫被打包到可執行程序中,直接發佈可執行便可使用。2)尋址方便,速度快

 446            

 447             缺點:   1)靜態庫的代碼在編譯時被載入可執行程序,因此靜態庫越大,可執行程序越大(這也致使了它的第一個優勢);

 448                     2)當靜態庫的改變了,可執行程序也必須從新編譯。

 449                     3)每一個使用靜態庫的進程都要將庫編譯到可執行文件中再加載到內存中,內存消耗嚴重。

 450

 451         5.問題1:

 452     13.生成動態庫:

 453         1.命名格式:libxxx.so

 454         2.製做:

 455             1)生成與位置無關的 .o; gcc -fPIC -c 編譯的.c文件 -I (.c文件中)頭文件的路徑;

 456                 例如: gcc -fPIC -c *.c -I ../include;

 457

 458             2) 打包;gcc -shared -o 生成的動態庫的名字 .o文件;

 459                 gcc -shared -o libCalc.so *.o ;

 460

 461         3.動態庫的使用:gcc main.c -o 可執行程序的名字 -I (main.c中頭文件路徑) 動態庫的路徑+動態庫的名字

 462                 gcc main.c -o app2 -I ../include lib/libCalc.so;    "注意:這裏面動態庫的路徑不加-L參數,生成的執行程序運行不起來"

 463

 464         4. ldd + 可執行程序;

 465             查看程序執行時,調用的動態庫。

 466        

 467         5.手動添加動態庫的方法:

 468             1)臨時添加:(測試的時候使用;)

 469             2)永久添加:(修改家目錄的bashrc文件)

 470             3)修改配置文件的方式:修改動態連接器的配置文件

 471                 更新動態連接器:

 472                 查看連接器的路徑:sudo ldconfig -v參數。

 473

 474         6.動態庫加載失敗的緣由:

 475             1)解決方案:

 476                 a. (臨時方案,用於程序測試)使用環境變量: LD_LIBRARY_PATH=動態庫的路徑;   而後倒入環境變量: export LD_LIBRARY_PATH

 477                 b.(永久設置。)修改動態連接器的配置文件:

 478                 c.(修改家目錄的 .bashrc文件);

 479         7.動態庫的優缺點:

 480             優勢:多進程共享一份庫文件,節省內存,易於更新 。

 481             缺點:相較於靜態庫而言庫函數訪問略慢。

 482     14.使用靜態庫的參數操做動態庫,看可否跑起來。(不能加靜態庫的操做參數)

 483    

 484 "-----第四天-----------------------------------------------------------------------------"

 485     15. 其餘命令:

 486         1) alias 當前命令="增強版的命令";

 487             alias gcc='gcc -std=c99';    使gcc 的默認編譯按照 c99 規範。(在家目錄的bashrc配置文件中);

 488         2)echo 取變量的值:echo $變量名;(取出變量的值)變量名前加 $;

 489             例如:echo $PATH;(取出環境變量的值);

 490             "取最近的函數的返回值:  echo $? "

 491 十一。windows中的動態庫

 492     1.  xxx.dll(windows中的動態庫名後綴);

 493     2." 動態庫與靜態庫發佈時的區別:"

 494

 495

 496 十二。gdb 調試:

 497     1.獲得包含調試信息的可執行性程序:

 498     gdb -g main.c -o app -I ../include ;

 499

 500     2.運行調試程序:

 501         gdb 可執行程序名;

 502        

 503     3.命令:

 504         1)執行命令:兩種  start 一行一行執行,執行過程當中能夠添加其餘參數調試。

 505                         run  直接執行到程序結束。

 506         2)查看程序內容: l (什麼都不加);l + 行號; l + 函數名; l + 函數名:行號;

 507

 508         3)加斷點:b 行數 ; 查看斷點信息:i  b;    刪除斷點:del b 斷點編號

 509

 510         4)繼續執行程序:c ; c + 斷點編號(跳到此段的位置); 打印內容:p  變量名;  往下執行一步:n

 511

 512         5)自動追蹤變量的值:display + 變量名;查看追蹤變量的編號:i display;  取消追蹤: undisplay + 追蹤變量編號

 513

 514         6)跳出循環:1)設置變量的值:set var 變量名=值;

 515                      2)在循環的的外面設一個斷點,跳到該斷點。

 516        

 517         7)獲取變量的類型:ptype 變量名;

 518        

 519         8)進入到函數體的內部:s ;跳到下一個斷點: c 。

 520        

 521         9)跳出當前函數:finish;

 522

 523         10)條件斷點:b 17 if i == 10(當i等於 10 時 17 行打斷點,注意:斷點不能設在 for 循環的那行,不會中止);

 524

 525 十三. Makefile 文件編寫;

 526     掌握內容:

 527         一個規則,兩個函數,三個自動變量

 528    

 529     1.命名:makefile;  Makefile;

 530     2.用途:

 531         項目代碼編譯管理;節省編譯項目的時間;

 532     3.Makefile 中的規則:

 533         目標:依賴;

 534             生成一個 app 執行程序;須要依賴的函數;

 535         命令:編譯命令;

 536        

 537         標準格式:"目標 : 依賴(依賴這個位置不必定非得有,有的時候是沒有的。以下面的 make clean:)

 538                          命令"

 539     操做界面的:make 目標;==========》  

 540     4.工做原理:

 541         1)若想生成目標,檢查規則中依賴的條件是否存在;若是不存在,尋找是否有規則用來生成該條件

 542

 543         2)檢查規則中目標是否須要被更新,必須檢查它的全部依賴;依賴中有任何一個被更新,則目標必須被更新。(規則:"依賴文件比目標時間晚,則須要被更新。")

 544

 545     5.Makefile編譯版本:"makefile中全部的函數都有返回值"

 546         1)版本1:

 547

 548             缺點:效率低,每次修改任意一處,都須要編譯全部的源文件。

 549

 550         2)版本二:

 551

 552             缺點:冗餘。

 553             "app:main.o div.o mul.o sub.o            //第一個條件

 554                 gcc main.o div.o mul.o sub.o -o app

 555

 556             main.o:main.c                             //第一個條件的依賴條件生成

 557                 gcc -c main.c

 558             div.o:div.c

 559                 gcc -c div.c

 560             mul.o:mul.c

 561                 gcc -c mul.c

 562             sub.o:sub.c

 563                 gcc -c sub.c"

 564

 565         3)版本三:(使用了變量)

 566             1.Makefile中的變量: 變量名=value

 567            

 568             2.Makefile中的自動變量:

 569                 1)$@:    規則中的目標

 570                 2)$<:    規則中的第一個依賴

 571                 3) $^:    規則中的全部的依賴

 572             注意: 這三個只能在命令中使用。

 573

 574             3.Makefile中本身維護的變量:

 575                 CPPFLAGS=頭文件的路徑;

 576

 577             缺點:相關的文件不能自動查找

 578             "代碼:

 579                 obj = main.o div.o mul.o sub.o         

 580                 target = app3

 581                 CPPFLAGS=-I ../aa/

 582

 583                 #第一條目標

 584                 $(target):$(obj)

 585                     gcc $(obj) -o $(target)

 586

 587                 #第二條目標

 588                 %.o : %.c

 589                     gcc -c $< $(CPPFLAGS)"

 590

 591

 592         4)    版本四:

 593             1.makefile 中的函數:

 594                 1)全部的函數都有返回值

 595                 2)wildcard---查找指定目錄下指定類型的文件

 596                         "src = $(wildcard ./*.c);"

 597                    patsubst---匹配替換

 598                            obj = $(patsubst %.c,%.o,$(src))

 599             缺點: 功能不夠強大

 600             "代碼:

 601                 src = $(wildcard ./*.c)

 602                 target = app

 603                 obj = $(patsubst %.c, %.o, $(src))

 604                 CPPFLAGS = -I ./

 605

 606                 $(target):$(obj)

 607                     gcc $(obj) -o $(target)

 608

 609                 %.o:%.c

 610                     gcc -c $< $(CPPFLAGS)"

 611

 612         5)  版本五:刪除編寫過程當中的臨時文件

 613             1.生成一個與終極目標無關的目標:clean

 614                 make clean

 615

 616             1.聲明僞目標:.PHONY:變量的名;

 617                 僞目標特色:makefile 不會檢查目錄下是否有這樣的文件,也不會對它的時間作檢查

 618

 619             2.-的做用:、該命令若是錯誤,跳過該命令,繼續執行下一條命令。

 620                 clean:

 621                     -rm $(obj);        有提示:(當前命令沒法執行時有提示)

 622               -f的做用:強制刪除當前   

 623                     -rm -f $(obj);    無提示:(當前命令沒法執行時無提示)

 624                 "代碼

 625                     src = $(wildcard ./*.c)

 626                     target = app

 627                     obj = $(patsubst %.c, %.o, $(src))

 628                     CPPFLAGS = -I ./

 629

 630                     $(target):$(obj)

 631                         gcc $(obj) -o $(target)

 632

 633                     %.o:%.c

 634                         gcc -c $< $(CPPFLAGS)

 635                     .PHONY:clean

 636                     clean:

 637                         -rm -f $(obj)"

 638

 639         終極目標:第一條目標所依賴的規則;

 640         "每級目標時間比每級依賴時間晚。"       

 641

 642 十四。linux系統的 IO 函數:

 643     linux 每運行一個程序(進程),操做系統都會爲其分配一個 0~4G 的虛擬內存空間(32位操做系統)。

 644    

 645     1.C庫函數:

 646         1)fopen 函數返回值:一個文件指針(結構體):(包含三個方面:1.文件描述符, 2.文件讀寫位置, 3.I/O緩衝區(內存地址));

 647             文件描述符:描述符表:至關於一個數組,大小爲1024;

 648             一個進程最多打開1024個文件;

 649

 650         2)緩衝區的數據往磁盤上寫內容的三種狀況:

 651             1.刷新緩衝區:(fflush)

 652             2.緩衝區已滿;

 653             3.正常關閉文件(fclose);  或者:main函數中(return, exit);

 654             "注意:標準C庫函數 有緩衝區,而linux 系統函數 沒有緩衝區 ";

 655         3)ELF(Linux下可執行程序的格式):

 656             ELF中存放的是源代碼,他有一個入口,main函數。主要分爲三段:.bss(未初始化的全局變量);.data(已初始化的全局變量);    text(代碼段) ;

 657

 658

 659         4) PCB:進程控制塊;其中有一個文件描述表(其中存儲文件描述符;一個文件佔用一個文件描述符),是一個數組,有1024個大小;因此一個進程以內最多隻能打開1024個文件。

 660             每打開一個新文件,則佔用一個文件按描述符,並且使用的是空閒的最小的一個文件描述符。

 661

 662     "代碼區是棧模型"。

 663

 664

 665

 666 "-----第五天-----------------------------------------------------------------------------"

 667 一.系統 I/O 函數:

 668     1.open() 函數當文件不存在時,建立文件,併爲它指定權限;(函數的第二個參數,各類宏定義; 第三個參數:指定權限,與掩碼的取反再按位與得出文件最後的權限)。;

 669         1)正常打開, 2)建立文件;  3)文件截斷;

 670     2.文件截斷:

 671    

 672     3. perror() 函數的使用:頭文件stdio.h; 打印錯誤信息。;

 673

 674     4. read() ;  size_t(無符號整型);   ssize_t(有符號整型);(UNIX 的類型);

 675

 676     5. linux系統函數的注意事項:須要判斷函數的返回值。-1,失敗; 

 677    

 678     6.Linux系統函數實現文件的拓展:

 679         第一步 lseek(fd, 1000, SEEK_END );

 680         第二步 write(fd, "a", 1);    (必須有一次寫操做)。

 681         "拓展的部分爲空洞文字;有空洞文字的文件叫空洞文件,做用: 提早佔用磁盤空間,下載中的應用:防止下載一半,空間不夠。"

 682

 683     7.stat()函數:

 684         1.off_t(unix 中的整型);

 685         2.應用(斷點續傳;)

 686

 687

 688     8.一些命令的穿透功能:如:vi; cat; (遇到軟鏈接時)

 689         不穿透的:如: rm;    (遇到軟鏈接時)

 690

 691     9.chmod()

 692

 693     10.chown()函數的參數查找;必須在配置文件中查找

 694

 695     11.unlink()函數;(刪除文件目錄項,使之具有被釋放的條件。)

 696         函數使用場景:實現可以自動刪除臨時文件;

 697         注意點:當文件在打開狀態時:open(),並無關閉;unlink,當close的文件的時候,會自動刪除。

 698         "例如:

 699             int fd = open("san.txt", O_RDWR);

 700             unlink("san,txt");  //刪除文件,當前狀態不會刪除

 701             write(fd, buf1, 102);

 702             lseek();

 703             read(fd, buf, 200);

 704             close(fd);            //此時文件 san.txt 纔會自動刪除

 705                       "

 706     12.chdir:修改當前進程的路徑

 707             int chdir(const char *path);  path:當前進程的名字。

 708

 709     13.getcwd:獲取當前進程的工做路徑。char* getcwd(char* buf, size_t size);

 710         參數:buf--緩衝區,存儲獲取到的工做路徑。

 711               size--緩衝區的最大容量。

 712

 713     14.mkdir--建立目錄: int mkdir(const char* pathname, mode_t mode );

 714         參數: pathname: 建立的目錄名。  mode: 目錄權限(8進制)。給出的權限通過換算以後纔會獲得最終權限。(mode & ~umask & 0777)   

 715        

 716

 717

 718    

 719

 720 "-----第六天-----------------------------------------------------------------------------"

 721

 722 1.版本控制:svn/git;

 723

 724 2.進程的概念:

 725     1)程序和進程;

 726         每一個進程操做系統會爲它分配 0-4G 的虛擬內存空間(32位操做系統); 其中0-3G爲用戶內存空間,進程能夠對它進行讀寫操做; 3G - 4G 爲系統內核空間,進程沒有讀寫權限。

 727         進程只能讀寫用戶空間,沒有權限讀寫內核空間(kernel);

 728     2)內存頁面的概念

 729         操做系統是按頁來管理內存的;每一個頁有4096個字節。

 730         還能夠設置頁面屬性:如char *str = "hello",字符串在只讀數據段,此時只能讀,不能寫。

 731

 732     3)進程的4種形態:0-3級; 0 級(內核態),最高; 3級(用戶態);最低。

 733

 734     2)併發:

 735     3)單道程序設計/多道程序設計

 736     4)CPU/MMU

 737     5)PCB:結構體;其中有一個指針指向文件描述符表;文件描述符表中存儲1024個指針;已經打開的文件結構體。

 738         每一個進程有屬於本身的PCB(進程的狀態描述符);可是多個進程只有一個內核區。

 739 3.環境變量控制

 740     1)echo $名稱;    查看該名稱的環境變量。

 741     2)查看系統的環境變量: env;

 742     3)獲取環境變量的值:char *getenv(const char* name);    獲取鍵name環境變量的值。

 743     4)設置環境變量:int    setenv(const char *name, const char *value, int rewrite);    將環境變量name的值設置爲 value。

 744                     若是環境變量 name 已存在;則 rewrite 非0,覆蓋原來的環境變量;rewrite爲0,則不覆蓋原來的環境變量。

 745     5)刪除環境變量: void unsetenv(const char *name) 刪除 name    的定義;

 746

 747     6)進程裏能夠設置本身的環境變量,避免設置在終端,影響他人。

 748 4.環境控制原語:

 749     1)fork:

 750     2)wait/waitpid

 751     3)

 752

 753 5. printenv.c

 754

 755 6.進程的狀態:4 種或 5 種,都對。 就緒, 運行, 睡眠, 中止。

 756

 757 7.CPU的組成狀態: 運算器,寄存器,控制器,譯碼器。

 758

 759     操做系統完成進程調度。(cpu進行時鐘週期運算)

 760     cpu的分時複用功能,使進程看起來像多進程。

 761     在單核 cpu 上,同一時間只能有一個進程處於運行狀態。那麼多核 cpu,就能夠有多個進程處於運行狀態。

 762 "8.子進程、父進程間的共享、不共享:"

 763         共享: 1.宿主目錄; 2.進程工做目錄; 3.信號處理方式;  4.環境變量;

 764                 5. 0-3G的用戶空間("讀時共享,寫時複製。"「特別是:全局變量」)  6.文件描述符(打開文件的結構體) 7.mmap創建的映射區。

 765        

 766         不共享:1.進程ID, 2.進程運行時間  3.鬧鐘;   4.未決信號集   5.PCB

 767

 768 8.進程原語:

 769     1)建立子進程。pid_t fork();    調用1次,返回兩次;在父進程返回子進程的 PID, 在子進程返回0.

 770     2) fork()的工做進程:先調用 creat(),建立一個進程, 在調用 clone(),給子進程複製父進程的內容;

 771     3)pid = fork();    //此時父子進程就都出來了。

 772     4)pid_t getpid();  返回調用進程的PID號;

 773        pid_t getppid();    返回調用進程的父進程的PID號

 774        當在子進程中 getpid(),獲得的值與 fork()父進程的返回值相等,都是這個子進程的id號

 775     5)父子進程:讀時共享,寫時複製。

 776     6)最大建立進程 個數;

 777 9.    uid_t getuid(void);        //返回實際用戶id;

 778     uid_t geteuid(void);     //返回有效用戶id;

 779     "注意: 文件實際用戶與有效用戶在建立該文件的家目錄下時,若是沒有修改,此時是相通的。

 780             當文件被拷貝到root目錄時,   "   

 781     設置用戶id; chmod 04755;  4 是設置用戶ID。  完後效果爲 -rwsr-xr-x;  s表示設置了用戶ID。

 782             做用:當執行此文件時,執行者有效用戶ID變爲此文件的全部者。

 783             設置用戶組ID: chmod 06777; 6 是設置用戶ID和組ID; 效果爲: -rwsrwsrwx;

 784

 785 10. exec族函數的使用:

 786     1)功能: 去磁盤中加載另外一個可執行程序,用它的代碼段、數據段替換掉當前可執行程序的代碼段、數據段;而後從後加載的這個程序退出,被替換的程序後續代碼就不執行了。(換核不換殼,)

 787     2)通常狀況下:與 fork() 函數聯合使用;。  同時exec族函數不會建立新進程, 因此該程序的 ID 不會改變。

 788

 789     3)函數的返回值: 成功沒有返回值,運行完畢,本身退出。

 790                       失敗返回 -1;

 791     4)exec族函數的規律: l(list):命令行參數列表。  p(path): 搜索file時使用path變量。

 792                           v(vector):使用命令行參數數組。  e(environment):使用環境變量的數組,不使用進程原有的環境變量,設置新加載程序的環境變量;

 793    

 794     5)int execl(const char *path, const char *argc, ...);

 795     例如:execl("./bin/ls", "ls", "-l", "-a", NULL);    這幾個參數的做用:其中第一個參數:"./bin/ls",命令的環境變量(即所在文件),不能夠改變,必須完整正確;

 796         "ls":佔位參數,能夠隨便寫,通常寫成該命令。(不能缺失,若是缺失了,就會把後面的命令參數變爲佔位參數,輸出結果會出錯。) "-l","-a"該命令的參數。   NULL:衛兵,執行到這裏時命令結束。

 797

 798 11. toupper():將小寫字母變爲大寫。

 799

 800 12.殭屍進程,孤兒進程:

 801     1)概念:

 802         殭屍進程:子進程終止,父進程未回收,子進程殘留資源(PCB)存放於內核,形成殭屍進程。

 803         孤兒進程:父進程先於子進程終止,則子進程成爲孤兒進程,而後被init進程領養。

 804

 805     1)S:睡眠狀態;  Z:殭屍狀態;

 806     2)殭屍進程的產生緣由:用戶空間釋放,內核空間的PCB沒有釋放,等着父進程回收。(它消耗的是內核當中的內存資源)

 807             即:子進程退出,父進程沒有回收子進程資源(PCB),則子進程變爲殭屍進程。

 808     3)子進程的PCB(在內核空間)沒有釋放,是留給父進程回收用的。只有父進程回收後,殭屍進程纔會消失。

 809     4)殺死殭屍進程的辦法是殺掉它的父進程。

 810

 811   孤兒進程:父進程先於子進程結束,則子進程變爲孤兒進程,子進程的變爲1號進程init進程,由1號進程領養。

 812

 813   "殭屍進程比孤兒進程更危險, 由於它不會自動關;,而孤兒進程會由 1 號進程領養,當它執行完畢後,會被 1 號進程回收"。

 814   作開發時主要避免的是殭屍進程的產生。用 wait(); waitpid(); 來避免殭屍進程的產生。

 815

 816

 817 13. pid_t wait(int* status);  (阻塞函數,等待回收子進程資源;若是沒有子進程,返回-1);

 818     1)返回值:回收的子進程的ID號,    wait(NULL);不關心子進程如何死亡,直接回收。

 819                                     wait(&st); 用st來保存子進程死亡時的狀態。

 820    

 821     2)    父進程的ID與它的進程組ID相同;子進程的組ID與父進程的ID相同。

 822         kill -9 -父進程的ID(即組進程的ID),這個進程組的全部進程都被殺死。"(注意 - 不能少)"

 823

 824 14.pid_t waitpid(pid_t pid, int *status, int options);    (設置非阻塞。)

 825     第一個參數 pid的值類型:    1) < -1; 回收指定進程組內的任意子進程。(由於父進程與子進程屬於統一進程組,父進程與孫子進程屬於不一樣的進程組,可是他們有血緣關係。)

 826                                     -1;回收任意子進程(只要有血緣關係就行。)

 827                                     0; 回收 當前調用 waitpid 一個進程組的全部子進程。

 828                                     > 0; 回收指定ID的子進程。

 829     第二個參數:保存子進程的推出狀態。

 830

 831     第三個參數:WNOHANG:若是沒有子進程退出,當即返回。(實現了非阻塞的 wait).

 832

 833 15. 阻塞函數:非阻塞函數:在文件open(O_NONBLOCK)的時設置宏;讀常規文件不會出現阻塞,當讀僞文件時會出現。

 834         例如:阻塞讀終端; 管道; 網絡;

 835

 836     設置非阻塞後:應設置輪詢。

 837        

 838

 839 "=========進程間的通訊(IPC)==========================================================================================================="

 840 一。IPC方法:Linux環境下,多個進程間的通訊,須要經過內核,在內核中開闢一塊緩衝區(賦予他用戶權限);進程1把數據從用戶空間拷貝到內核緩衝區,

 841     進程2 把數據從內核緩衝區拷讀走,內核提供的這種機制稱爲進程間的通訊(IPC)。

 842

 843     進程間的通訊;四種方法:1.pipe管道 2.fifo有名管道,3.內存共享映射 4.Unix Domain Socket;

 844     管道(使用最簡單);信號(開銷最小);共享映射區(速度最快,效率最高); 本地套接字(最穩定);

 845

 846 二。pipe管道:

 847 1.管道的特性:數據只能一個讀,一個寫,必須是一個方向。

 848             半雙工:數據同一時刻只能有一個流向。即只能父進程寫,子進程讀; 或子進程寫, 父進程讀。

 849             全雙工:數據同一時刻能夠兩個方向。

 850             單工:數據只能同一個方向流動。

 851             dup2(int oldfd, int newfd);        將第一個參數拷貝給第二個參數。

 852             1.其本質是一個僞文件(實爲內核緩衝區)

 853             2.有兩個文件描述符引用,一個讀端,一個寫端。

 854             3.規定數據從管道的寫端流入,從讀端流出。

 855  

 856   管道的原理:管道實爲內核使用環形隊列機制,藉助內核緩衝區(4K)實現的。

 857

 858   管道的侷限性:1.數據不能本身寫,本身讀;

 859                   2.管道中的數據不能反覆讀取,一旦讀走,管道中再也不存在。

 860                   3.採用半雙工通訊方式,數據只能在單方向上流動。

 861                   4.只能在有血緣關係之間的進程使用管道。

 862                   5.只能進行單向通訊,雙向通訊須要創建兩個管道。

 863

 864 2. pipe()建立管道,用於有血緣關係之間的通訊。(採用環形隊列實現的)

 865     管道使用半雙工通訊; 建立完管道完後,肯定通訊方向:父寫子讀,或子寫父讀。

 866     若是想建立多條管道,必定要先pipe(),再fork(),使子進程得以繼承管道。

 867

 868     使用管道時的四種注意狀況:

 869     1) 寫段關閉,讀端讀完管道里的內容時;再次讀,返回0,至關於讀到文件末尾EOF;

 870     2)寫端未關閉,寫端無數據, 讀端讀完管道里的數據時,再次讀,阻塞。

 871     3)讀端關閉, 寫段寫管道,產生SIGPIPE信號,寫進程默認狀況下會終止進程。

 872     4)讀端未讀管道數據,當寫段寫滿管道後,在此寫,阻塞。

 873     5)使用管道,無須open,但需手動close。

 874

 875     管道的緩衝區大小:1.函數的方法:fpathconf(int fd, int name);  第一個參數爲管道描述符;第二個參數爲狀況標識符。

 876                         2.命令: ulimit -a;    查看系統 軟硬件限制。

 877

 878 3.    總結:

 879     1.讀管道:

 880         1.管道中有數據,read返回實際讀到的字節數;

 881         2.管道中無數據,寫端都被關閉,read返回 0,至關於讀到文件末尾;

 882                         寫端未關閉,read函數阻塞等待,(期待不久的未來會有數據到來,但此時會讓出CPU資源)

 883     2.寫管道:

 884         1.管道讀端所有關閉;進程異常停止(返回一個終止信號);

 885         2.管道讀端未關閉:

 886             1)管道已寫滿,write阻塞等待

 887

 888             2)管道未寫滿,write將數據寫入,返回實際寫入的字節數;

 889

 890

 891 "==========================================================================="

 892 4.設置非阻塞管道的兩種辦法:

 893     1)fcntl函數設置非阻塞管道;

 894         int flg = fcntl(fd, F_GETFD);

 895         flg |= O_NONBLOCK;

 896         fcntl(fd, F_SETFL, flg);

 897     2)打開文件時直接設置非阻塞;

 898         int fd = open("/dev/tty", O_RDWR | O_NONBLOCK);

 899 當讀取一個非阻塞文件,可是此時沒有內容,會出錯,錯誤碼爲EAGAIN;

 900 5. read() 函數的返回值四種狀況;因爲非阻塞設置的存在.

 901     1.返回值 > 0; 讀到的字節數

 902     2.返回值 < 0; 讀到文件末尾

 903     3.返回值 == -1;可是errno != EAGAIN  或 EWOULDBLOCK

 904         if( ret == -1) {

 905         if(errno ==  EAGAIN)

 906         {

 907             說明文件被設置爲非阻塞方式讀取,此時數據沒有到達。

 908         }

 909         else

 910         {

 911             失敗;

 912         }

 913     }

 914     4.返回值 == -1, 可是errno == EAGAIN  或 EWOULDBLOCK;

 915         說明此時文件被設置爲非阻塞方式讀取,數據尚未到達。

 916 "========================================================================"

 917 三. fifo有名管道:解決無血緣關係的進程通訊;

 918     1.介紹:

 919         FIFO文件在磁盤上沒有數據塊,僅僅用來標識內核中的一條管道。各進程能夠打開這個文件進行read/write,其實是在寫內核通道,這樣就實現了進程間的通訊。

 920     1.建立fifo的方法:

 921         1)在終端建立一個有名管道;(不經常使用)用命令;"mkfifo 管道名";

 922         2)在代碼運行時建立一個有名管道;(經常使用)用函數;int mkfifo(const char*pathname, mode_t mode);成功返回 0,失敗-1;

 923

 924     2.利用fifo實現非血緣關係進程間通訊

 925         1.進程使用 「同一個fifo」 完成進程間通訊。

 926         2.一個進程以只讀方式打開read端,一個程序以只寫打開寫段。

 927         3.一根管道能夠打開多個讀端,多個寫段。(一個寫段多個讀端; 或 一個讀端多個寫段);

 928    

 929     3.多種特殊狀況:

 930         當一個寫端多個讀端時: 每一個讀端讀取到的數據都不相同,由於從管道中讀數據,讀走以後,管道中的這個數據就不存在了;此時每一個讀端讀到的全部內容合在一塊兒爲

 931                                 管道寫端寫入的數據

 932         當多個寫端一個讀端時, 每一個寫端寫入的數據都會被這個讀端讀取出來;此時管道讀到的數據爲全部寫端寫入的數據。

 933                            

 934 四。mmap 內存映射:

 935

 936         從磁盤映射到kernel區,同時kernel區這段內存(映射佔用的)開放了用戶區的權限;因此進程能夠進行訪問

 937

 938 1.文件是應用於進程間通訊

 939     1)父子進程之間

 940         能夠用文件進行通訊;

 941     2)非血緣關係進程間通訊

 942         能夠用文件進行通訊;

 943    

 944 2.創建映射區,完成進程間通訊            

 945     1)mmap函數;六個參數的不一樣意義

 946

 947     2)注意事項

 948         1.open的時候能夠建立一個新文件,可是用此文件建立映射區時,大小不能爲0;(能夠進行文件拓展後再用來建立映射)

 949             mmap使用的時候常常出現總線錯誤,一般是因爲共享文件存儲空間大小引發的。

 950            

 951         2.建立映射區的時候, 隱含着一次對文件的讀操做;因此文件打開的方式只能爲"讀寫;或讀"。

 952           當 MAP_SHARED(對內存的修改將反應到磁盤空間)    時,要求 映射區的權限 <= 文件打開的權限。

 953           當 MAP_PRIVATE(對內存修改不會反應到磁盤空間)  時,此時則沒有要求。(mmap中的權限是對內存的限制);

 954

 955         3.映射區建立完後關閉文件按描述符,對映射區沒有影響。

 956         4."最後一個參數,偏移量必須是4K的整數倍。"

 957         5.munmap函數傳入的地址必定要是mmap的返回地址。堅定杜絕對mmap函數的返回值進行++操做

 958         6.mmap建立映射區出錯的機率很是高,必須進行出錯判斷。

 959

 960     3)父子進程間的mmap(用戶空間獨立,內核去各進程共享。)

 961         1.先mmap建立映射區

 962         2.再fork()共享映射區內存首地址

 963         3.指定MAP_SHARED;(必須是 SHARED);

 964

 965     4)非血緣關係進程間通訊

 966         1.使用「同一個文件」建立映射區

 967         2.兩個進程,一個以read映射區,一個以write方式打開映射區;

 968         3.指定 MAP_SHARED;

 969         4)MAP_ANONYMOUS(匿名映射); 不能夠用來通訊

 970         5)/dev/zero(系統的僞文件); 不能夠用來通訊

 971     5)匿名映射

 972         linux 建立匿名映射:第四個參數添加 MAP_ANON或MAP__ANONYMOUS;(注意這個匿名宏,只有Linux操做系統可使用)。

 973

 974         UNIX(沒有上述的匿名宏)。使用系統中的特殊文件(/dev/zero;(無限讀,能夠用來建立匿名映射))

 975

 976 3.數據能夠重複讀取;(即多個讀端讀取一個寫端,讀取的內容相同,與fifo不一樣,取決於讀取的數據)。

 977

 978

 979

 980 "====================進程間的通訊(IPC)================================================================================================"

 981

 982 文件名最大爲255字節(byte);

 983 "============================硬連接========================"

 984 建立一個硬連接:

 985     1.dentry(包含文件名,文件屬性)

 986     2.一個文件包含(三大塊):文件的名字; inode(指向文件屬性) ;文件內容;

 987     3.

 988 "============================硬連接========================"

 989

 990 strace 跟蹤程序的運行時函數的系統調用;

 991

 992 "===信號========================================================================================================================"

 993 一.信號的概念:

 994     1.本質:

 995         軟中端;信號經過內核發送,內核處理的。

 996     2.特性:

 997         1)簡單,2)不能攜帶大量信息; 3)知足某一條件

 998     3.信號機制:

 999         軟中端;信號經過內核發送,內核處理的;經過軟件的方法實現的,有較強的延遲性。

1000        

1001     3.四要素:

1002         1.信號編號, 2.信號名稱, 3。默認處理動做,4.對應的事件。

1003        

1004         2.信號的默認處理動做(5種):

1005             1.終止進程(term);2.忽略(Ign:信號被處理丟棄);3.終止進程併產生core文件(core);

1006             4.Stop(暫停);  5.Cont (繼續);

1007

1008     4.名詞稱呼

1009         1.信號的狀態:

1010             1.產生;

1011             2.未決:處於產生和遞達中間,因爲阻塞不能遞達、處理。

1012             3.遞達;信號遞達後內核會當即處理。(也就是說,他倆常常綁定在一塊兒,信號遞達就表明這信號被處理。)

1013             4.處理:(信號必須遞達)

1014                 1.忽略處理(信號已經處理,丟棄操做); 2.執行默認操做,  3.捕捉(不執行默認操做,來指定操做讓其執行;)

1015            

1016         2.未決信號集:(pending)

1017             在PCB中,以位圖的方式存在。

1018             記錄信號是否被產生,而且被處理。 內核處理信號的依據。用戶不能直接修改未決信號集。

1019

1020         3.阻塞信號集/信號屏蔽字:(mask)

1021             在PCB中,以位圖的方式存在。    mask影響pending;用戶只能夠經過mask來影響pending。

1022             記錄信號是否被設置屏蔽。用戶影響信號的依據。

1023

1024         4. 1-31 號信號,常規信號(不支持排隊); 34-64 號信號,實時信號(支持排隊)

1025

1026         5.特殊信號:(兩個);

1027             9 號、 19 號信號;不容許捕捉,忽略,甚至不能設置屏蔽。

1028

1029         6.產生段錯誤的方式(三種);

1030             1.訪問非訪問區域。0x1000   printf();            mmu---沒有映射該虛擬內存

1031             2.對只讀區域進行寫操做。 char* p = hello; p[1] = 'H';      mmu---映射的虛擬內存對應的物理內存權限不足。 0 內核權限; 3 用戶權限

1032             3.內存溢出;  char buf[10];  buf[10] = '10'; buf[100] = '28';  mmu---沒有映射該虛擬內存。

1033

1034 二.產生信號:

1035     1.常見的產生信號方法:

1036         1.按鍵產生:ctrl+c;

1037         2.系統調用:如kill

1038             kill(pid_t pid, int sig); 向指定進程或進程組發送指定信號;

1039                 第一個參數: pid > 0; 向指定進程發送指定信號;    pid == 0; 向調用kill函數的進程組的全部進程發送該信號

1040                             pid == -1; 發送信號給系統中有權限的全部進程;  pid < -1; 發送信號給指定的進程組|pid|;

1041                 第二個參數: 信號。(不一樣的平臺環境下,信號的編號不一樣;可是信號的宏定義相同,因此通常使用宏名)。

1042

1043             raise() 給當前進程發送指定信號;

1044             abort() 向當前進程發送SIGABRT信號;

1045         3.軟件條件產生:如,定時器alarm;

1046             alarm:每一個進程有且只有惟一一個定時器。

1047             返回值特殊:上次定時剩餘的時間。定時(採用天然定時),與進程狀態無關!!!,不管處於何種狀態,都會計時。;

1048             取消鬧鐘: alarm(0);    實際執行時間 = 系統時間+用戶時間+等待時間。

1049              定時的單位是:秒。

1050             setitimer(); 定時單位單位:微妙;

1051                 三個參數:

1052

1053

1054         4.硬件異常產生:如,非法內存訪問(段錯誤);內存對齊出錯(總線錯誤);除0(浮點數除外)。

1055

1056    

1057         5.命令產生:如kill命令

1058

1059 三。信號操做函數;

1060     1.信號集 set:           

1061         sigset_t   set;

1062

1063         sigemptyset(&set)  清空集合 

1064

1065         sigfillset(&set)  置1集合 

1066

1067         sigaddset(&set, 待添加的信號名稱) 添加信號到集合中

1068

1069         sigdelset(&set, 待刪除的信號名稱) 刪除信號到集合中

1070

1071         sigismember(&set, 待判斷的信號名稱)判斷信號是否在集合中  -- 》 1:在 0:不在; -1;錯

1072

1073     2.mask(信號屏蔽字/阻塞信號集)操做

1074         sigprocmask();用來屏蔽信號、解除信號;其本質是讀取或修改進程的信號屏蔽字(PCB中);

1075         "注意:屏蔽信號只是將信號處理延後執行(延至解除屏蔽), 而忽略表示將信號丟棄。"

1076         參數:第一個參數 how 的取值:假設當前的信號屏蔽字爲mask;

1077                 1.SIG_BLOCK:當how設置爲此時,set表示要屏蔽的信號。至關於mask= mask|set;

1078                 2.SIG_UNBLOCK:當how 設置爲此時,set 表示要解除的信號。至關於:mask = mask & ~set;

1079                 3.SIG_SETMASK; 當how 設置爲此時,set = mask;

1080             第二個參數: set 傳入參數:用來操做mask的set集合。

1081             第三個參數: oldset 傳出參數。記錄舊有的mask狀態。

1082

1083     3.pending操做

1084         int sigpending(sigset_t *set);傳出參數

1085         參數:獲取未決信號集

1086         返回值:存在返回 1; 不存在返回 0;

1087

1088 四。信號捕捉

1089     1.signal:(註冊信號的捕捉處理函數)

1090         參數:1.信號編號 2.捕捉後調用的執行函數(是一個函數指針。即回調函數);

1091         返回值:捕捉的函數句柄。

1092

1093     2.sigaction: 1)信號捕捉函數執行期間,本信號被自動屏蔽(取決於:sa_flags) 2)信號捕捉函數執行期間,信號屢次產生,只記錄一次。

1094

1095      函數原型:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

1096          參數解析: 1)第一個參數:信號名稱或編號;要捕捉的信號。

1097                     2)第二個參數:新處理動做傳入,是一個結構體。

1098                            1)sa_handler: 1)函數指針,捕捉信號後執行的回調函數;2) SIG_IGN 表示忽略; 3)SIG_DFL 表示執行默認操做。

1099                         2)sa_mask; 信號屏蔽字/阻塞信號集;捕捉函數執行期間的屏蔽字,此中的信號在捕捉函數執行期間自動屏蔽。

1100                         3)sa_flags: 1) 0; 表示:信號捕捉函數執行期間,要捕捉的信號被自動屏蔽(即第一個參數)。

1101                                     2)SA_SIGINFO: 選用sa_sigaction來指定捕捉函數;

1102                                     3)SA_INTERRUPT: 系統調用被信號中斷後,不重啓;

1103                                     4)SA_REATART: 系統調用被信號中斷後,自動重啓。

1104                                     5)SA_NODEFER: 在捕捉函數執行期間不自動屏蔽捕捉的信號;

1105

1106                        4) sa_sigaction: 函數指針, 三個參數,void (*sa_sigaction)(int, siginfo_t*, void*);指定帶參數的信號捕捉函數。

1107                     3)第三個參數:舊處理動做傳出;

1108             返回值: 0 表示成功, -1 表示失敗,並設置errno ;

1109     3.信號捕捉特性:

1110         1)捕捉函數執行期間,屏蔽字由sa_mask指定。

1111         2)捕捉函數執行期間,被捕捉的信號自動屏蔽; 由sa_flags = 0 決定;

1112         3)"捕捉函數執行期間,常規信號不支持排隊,屢次產生只記錄一次。"   

1113         常規信號爲:1-31 信號; 實時信號爲 34-64 信號。

1114         詳細過程:進程正常運行時,默認PCB中有一個信號屏蔽字,假定爲☆,它決定了進程自動屏蔽哪些信號。當註冊了某個信號捕捉函數,捕捉到該信號之後,

1115            要調用該函數。而該函數有可能執行很長時間,在這期間所屏蔽的信號不禁☆來指定。而是用sa_mask來指定。調用完信號處理函數,再恢復爲☆。

1116    

1117     4.信號內核實現捕捉函數思想:

1118         信號捕捉函數是 回調函數; 由內核在信號產生、遞達以後負責回調。

1119         調用結束應該返回內核空間,再返回用戶空間。

1120

1121     5.內核實現信號捕捉的通常過程

1122         1)回調捕捉函數; 2)調用結束先返回內核。

1123

1124         「注意:此處加圖片:」

1125 五。竟態條件(時序竟態)

1126     1.pause() 函數:主動形成進程掛起,等待信號喚醒。調用該系統調用的進程將處於阻塞狀態(主動放棄CPU),知道有信號到達將其喚醒。

1127         int pause(void); 返回值:-1,並設置errno == EINTR;

1128         注意:

1129                 1) 喚醒pause()函數的信號不能執行默認操做、忽略、屏蔽。緣由:

1130                     1)若是信號的默認動做是終止進程,則進程終止,pause函數不會有機會被調用。

1131                     2)若是信號默認動做是忽略、屏蔽,則進程繼續掛起,pause不會調用。

1132                 2)若是信號的處理動做是捕捉,則【捕捉函數處理完後,pause被調用返回-1,而且errno == EINTR,表示被信號終端,即喚醒】;

1133                 3)綜上所訴:能喚醒pause()函數的信號,只能是被捕捉的信號;

1134                 

1135     2.時序竟態:

1136         1.時序問題產生的緣由: 1)系統負載嚴重; 2) 信號不可靠機制;

1137

1138         2.解決時序問題:

1139             1)使用原子操做;將解除信號屏蔽與掛起等待合併成一個步驟。sigsuspend() 函數具備這個功能。在對時序要求嚴格的場合下都應用

1140                 sigsuspend 替換 pause。"(解除信號屏蔽+掛起等待信號)----》原子操做---》sigsuspend()函數"

1141                 int sigsuspend(const sigset_t *mask); 掛起等待信號。

1142                     函數詳解: 1)主動形成進程掛起,等待信號; 2)在這個函數調用期間屏蔽字由它的參數決定; 3)函數調用結束屏蔽字恢復爲原值;4)原子操做

1143             2)提前預見,主動規避。這種錯誤,無法用gdb調試出來。

1144

1145     3.全局變量的異步IO:

1146         存在的問題:

1147             1.多個進程對 同一 個全局變量進行寫操做,存在問題。(如:信號回調函數中的全局變量和主函數中的全局變量爲同1個,內核進程和主進程都對

1148                 全局變量進行了寫操做,很是容易出問題)。

1149             2.寫操做時沒有任何 同步 機制。(加鎖機制)

1150

1151             「注意:此處有代碼,父子進程數數,代碼1,主進程和內核對同一個全局變量進行寫操做,出問題;

1152                                              代碼2,全局變量只由主進程進行一次賦值操做後,主進程和內核進程對它的只讀操做,沒有出問題」

1153

1154     4.可重入、不可重入函數:

1155         注意:

1156             1)不可重入函數:函數內部含有全局變量、靜態變量,使用malloc、free;

1157             "2)信號捕捉函數應設計爲可重入函數;(與上面的相反的就是可重入函數)。"

1158             3)信號處理程序調用的可重入的系統調用函數;可參閱 man 7 signal;

1159             4)沒有包含在上述列表中的系統調用函數大多數是不可重入的,其緣由是:

1160                 a) 使用了靜態數據結構,

1161                 b) 調用了malloc 或free

1162                 c) 是標準I/O函數 ;

1163

1164

1165 六。SIGCHLD信號 -------IGN(該信號的默認動做是忽略)

1166     1.該信號的產生:

1167         1)子進程終止;

1168         2)子進程接收到SIGSTOP信號中止時;

1169         3)子進程處在中止態,接收到SIGCONT後喚醒時;

1170         綜上所述:只要子進程的狀態發生變化,會對父進程發出SIGCHLD信號,默認處理的動做是忽略。

1171

1172     2.藉助 SIGCHLD 子進程回收。

1173         1)wait()--------阻塞等待子進程結束;

1174         2)waitpid()--------設置不阻塞(第二個參數WNOHANG)。若是這樣設置,要設置輪詢,才能將子進程回收。

1175         3)信號捕捉---子進程回收;

1176

1177     3.注意:

1178         1)子進程繼承了父進程的 信號處理動做和 信號屏蔽字(mask),但並無繼承父進程的 未決信號集(sigpending)。

1179         2)註冊信號捕捉函數的位置,和與其餘進程發出信號的配合(必須在捕捉信號發出以前完成註冊)。

1180         3)在捕捉函數中回收子進程(多個),必定要用循環,才能夠作到,一次進入回收多個子進程;不然,會有子進程遺漏,未被回收,形成殭屍進程。

1181

1182         「參考代碼」

1183

1184 七。信號傳參:

1185     1.int sigqueue(pid_t pid, int sig, const union sigval value); 成功返回0; 失敗-1;

1186         sigqueue 向指定進程發送信號的同時攜帶參數(即它的第三個參數);

1187         "注意:攜帶的數據。若是攜帶的是 地址:需注意,不一樣進程之間虛擬地址空間各自獨立,將當前進程地址傳遞給另外一進程沒有實際意義"

1188     2.捕捉信號傳參

1189         1)用該函數捕捉信號傳遞的數據: int sigaction(int signum, const struct sigaction* act, struct sigaction* oldact);    

1190         2)當註冊信號捕捉函數,但願得到更多關於該信號的信息,不該使用 sa_handler, 而應使用 sa_sigaction。 但同時 sa_flags 必須指定SA_SIGINFO.

1191             siginfo_t 是一個成員十分豐富的結構體,攜帶者該信號的各類相關信息。

1192            

1193 八。中斷系統調用

1194     1.慢速系統調用(形成當前系統永久阻塞的)

1195         1)如read, write, wait, pause, sigsuspend, 都是慢速系統調用 ;

1196         2)概念: 可能使進程永遠阻塞的一類系統調用;若是再阻塞期間收到一個信號,該系統調用被中斷,再也不繼續執行;也能夠經過設置,使其中斷後再從新啓動。

1197         3)特色:慢速系統調用被中斷的相關行爲,實際上就是pause的行爲: 如read()

1198             1) 信號不能被屏蔽, 執行默認動做, 忽略;

1199             2)信號的處理方式必須被捕捉;   

1200             3)中斷後返回-1, 設置errno爲 EINTR(表示:「被信號終端」);

1201

1202         4)設置sa_flags 參數來決定它終端後的行爲:

1203                 0           表示被捕捉的信號,在捕捉函數執行期間被自動屏蔽

1204                 SA_NODEFER    表示被捕捉的信號,在捕捉函數執行期間不被自動屏蔽

1205                 SA_INTERRURT 表示慢速系統調用,若被信號打斷,再也不重啓

1206                 SA_RESTART  表示慢速系統調用,若被信號打斷,重啓

1207                 SA_SIGINFO  表示捕捉函數是3參的sigaction,需指定爲這個宏名

1208

1209     2.其餘系統調用:

1210         如Lgetpid(), fork();

1211

1212 十。終端

1213     1.字符終端(虛擬終端),圖形終端(僞終端),網絡終端(僞終端)。

1214     2.線路規程(line discipline):

1215         像一個過濾器,對於某些特殊字符並非讓它直接經過,而是作特殊處理,好比ctrl+c,對應的字符並不會被用戶程序read讀到,而是被線路規程截獲,

1216         解釋稱SIGINT信號發送給前臺進程,一般會使該進程中止。線路規程應該過濾哪些字符和作哪些特殊處理是能夠配置的。

1217     3.在終端設備(如鍵盤)上輸入內容進入進程的順序:

1218         終端設備--》終端設備驅動--》line discipline(線路規程過濾)---》系統調用(普通內容)---》用戶進程

1219                                                                  ---》內核特殊字符(解釋稱信號)--》內核 前臺進程。;

1220     4.一套僞終端由一個主設備(PTY Master)和一個從設備(PTY Slave)組成;主設備在概念上至關於鍵盤、顯示器,只不過他不是一個真正的硬件而是一個內核模塊;

1221         操做它的也不是用戶,而是另一個內核模塊。        網絡終端或圖形終端窗口的shell進程以及它啓動的其餘進程都認爲本身的控制終端是僞終端從設備。               

1222

1223 十一。進程組       

1224     pid_t getpgid(pid_t pid);            返回指定進程組的ID

1225     pid_t getpgrp(void);                 返回調用函數進程組的ID

1226     int setpgid(pid_t pid, pid_t pgid);    設置某個進程的進程組ID; 成功返回0;失敗-1;

1227     1.當父進程建立子進程時,默認子進程與父進程屬於同一進程組。其進程組ID==父進程的ID。

1228     2.特性:

1229         1)進程組ID == 組長ID

1230         2)進程組的生命週期: 只要進程組中有一個進程存在,該進程組就存在,"與組長進程是否終止無關"。

1231                         進程組建立到最後一個進程離開(終止或轉移到另外一個進程組)。

1232     3.一個進程能夠爲本身或子進程設置進程組ID。

1233    

1234     4.修改一個進程的進程組ID需注意:

1235         1)如改變子進程爲新的組,應在fork後,exec前。

1236         2)權限問題。非root用戶只能改變本身和它建立的子進程的進程組。

1237

1238 十二。會話。

1239     pid_t getsid(pid_t pid);獲取該進程的會話ID(若是查看當前進程的會話ID,參數爲0就行。本身測試吧)。成功:返回會話ID; 失敗:返回-1,並設置errno .

1240     pid_t setpid(void); 建立一個會話,以本身的ID爲新會話的ID,同時也會成爲一個新的進程組。 成功:返回調用進程的ID;失敗,-1;

1241     1.會話:進程組的集合。

1242     建立會話應注意:

1243         1.建立會話的進程不能是進程組組長;同時建立的進程變成新會話首進程(即組長)。

1244         2.建立完後該進程成爲新進程組的組長進程。

1245         3.須要有root權限;(ubauntu不須要)

1246         4.新會話丟棄原有的控制終端,該會話沒有控制終端(也就沒法與用戶進行交互)。

1247         5.該調用進程是組長進程,則出錯返回。(與1 相同)。

1248         6.新建會話時,先調用fork,父進程退出;子進程建立會話(調用setsid()函數)。

1249        

1250     "注意:子進程不會隨着成爲新的進程組組長,而其父進程發生改變。"

1251

1252

1253 十三:守護進程:

1254     1.Daemon(精靈)進程,即守護進程。

1255         特徵:  1.位於Linux後臺,服務進程。

1256                 2.獨立於控制終端(即沒有控制終端),週期性的執行某任務,等待某事件

1257                 3.不受用戶的註銷、登陸而終止;(注意:不是關機)。

1258                 4.一般採用以d結尾的名字。

1259                

1260     2.建立守護進程的模型:

1261         1.建立子進程,父進程退出

1262             全部工做在子進程中進行,形式上脫離了控制終端。

1263         2.在子進程中建立新會話

1264             setsid()函數

1265             使子進程徹底獨立出來,脫離控制;

1266

1267         3.改變當前目錄爲根目錄;

1268             chdir()函數;

1269             目的:防止佔用可卸載的文件系統。

1270             也可換成其餘目錄,只要該目錄穩定,不會被卸載(當時卸載的優盤目錄);

1271

1272         4.重設文件掩碼;

1273             umask()函數:

1274             目的: 防止繼承的文件建立屏蔽字拒絕某些權限;

1275                    增長守護進程的靈活性;

1276

1277         5.關閉文件描述符

1278             繼承的打開不會用到,浪費系統資源,沒法卸載。

1279

1280         6.執行守護進程核心工做

1281

1282         7.設置守護進程退出。

1283

1284 "===信號========================================================================================================================"

1285

1286

1287 "===線程========================================================================================================================"

1288

1289 一。線程概念

1290     1.什麼是線程

1291         1)線程:LWP(light weight process):輕量級的進程,擁有獨立的PCB,共享進程地址空間,Linux下線程是最小的執行單位。

1292         

1293     2.線程與進程的區別、聯繫

1294         進程獨享地址空間;  線程共享。

1295         進程是最小的分配資源單位;  線程是最小的執行單位。

1296         各自有獨立的PCB。

1297

1298     3.內核實現線程的原理:

1299         1.建立線程與建立進程相似;調用底層函數clone();

1300         2.有不一樣的PCB,但線程共享進程地址空間---》PCB各線程持有相同頁目錄---》三級映射一致。

1301         3.以每一個線程的LWP號, 做爲內核分配執行單位的依據。

1302         4.線程的ID != LWP;

1303         5.線程是寄存器與棧的集合。

1304

1305     3.線程之間共享、不共享那些東西

1306         共享:

1307             1)文件描述符; 2)信號的處理方式; 3)用戶ID和組ID;

1308             4)工做目錄位置; 5).text/.data/.bss/.ordata/heap-----》用戶空間(0-3G ,棧空間除外) ;

1309         不共享:   

1310             1)線程ID; 2)用戶stack(棧空間);   3)內核stack(棧空間);

1311             4)信號屏蔽字;        5)errno變量;      6) 線程優先級

1312

1313     4.線程的優缺點

1314         優勢:

1315             1)線程間通訊能夠經過----全局變量 。(進程間不共享全局變量 --- mmap 映射)

1316             2)開銷小,節省空間

1317             3)程序的併發性提升。

1318

1319         缺點:

1320             1)第三方庫函數pthread,穩定性差;

1321             2)gdb調試工具支持很差。

1322             3)信號支持好(通常不要在線程中使用信號)。

1323

1324

1325 二。線程的控制原語:【重點】

1326     1.建立線程:

1327         int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

1328         參數一:    傳出參數,建立的線程ID;

1329         參數二:    線程屬性,通常採用默認的(用 NULL)。

1330         參數三:    子線程的操做函數。

1331         參數四:    子線程操做函數的參數。

1332         返回值: 成功:0 ; 失敗:錯誤號;

1333

1334     2.獲取線程的ID

1335         pthread_t pthread_self(void);

1336         參數:無u;

1337         返回值:    成功:線程ID號。  失敗:無。

1338

1339     3.將當前線程退出:

1340         void pthread_exit(void *retval);

1341         參數一:線程退出值(void*類型); NULL:無退出值。

1342         返回值:無;

1343         對比:

1344             return :     返回到調用者那裏去;

1345             exit() :        進將當前進程退出;

1346             pthread_exit();    將當前線程退出;

1347

1348     4.阻塞等待子線程退出,獲取退出狀態。

1349         int pthread_join(pthread_t thread, void** retval);

1350         參數一:      回收的線程ID;

1351         參數二:    被回收線程退出值。(NULL 表示不關心線程退出值)

1352         返回值:    成功:0;  失敗:錯誤號。

1353

1354     5.實現線程分離:

1355         int pthread_detach(pthread_t thread);

1356         參數一:待分離的線程ID;

1357         返回值:成功:0; 失敗:錯誤號。

1358

1359     6.殺死(取消)線程。

1360         int pthread_cancel(pthread_t thread);

1361         參數一:欲殺死的線程ID;

1362         返回值:成功:0; 失敗:錯誤號。

1363         注意:調用該函數時,欲殺死的線程必須調用系統調用函數(如:write,printf);以使線程進入內核,到達 記錄點/取消點。

1364             或者調用檢查函數(。。test)等會查一下;

1365         終止線程的方式:return;

1366                         pthread_exit();

1367                         pthread_cancel();

1368

1369     7.比較兩個線程

1370         int pthread_equal(pthread_t t1, pthread_t t2);

1371         參數1、二:比較的兩個線程ID號。

1372

1373     4.線程、進程控制原語對比;

1374             線程                               進程

1375         pthread_creadte();                         fork();

1376         pthread_self();                            getpid()---getppid()---getpgid()---getsid();

1377         pthread_join();                            wait()---waitpid();

1378         pthread_exit();                            exit()----return;

1379         pthread_cancel();                        kill();

1380         pthread_detach();---分離

1381         pthread_equal();----比較

1382

1383 三。NPTL

1384     pthread庫版本;

1385     查看:getconf GNU_LIBPATHREAD_VERSION

1386     gcc編譯指定 ---lpthread 選項。

1387

1388 四。線程的屬性【擴展】

1389     可在建立線程以前設置修改其默認屬性:

1390     pthread_attr_t 結構體內容:1)線程分離狀態; 2)線程棧空間大小; 3)線程警惕區大小;  4)線程棧低地址;。。。。。

1391

1392     1.屬性初始化

1393         pthread_attr_init();

1394         參數:attr:(傳出參數),待初始化的結構體。

1395         返回值:成功;0 ; 失敗:錯誤號;

1396

1397     2.銷燬自設屬性;

1398         pthread_attr_destroy(); 使用時機: 線程建立完畢。

1399

1400     3.線程分離狀態:

1401         1) int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate); 獲取線程分離狀態。

1402             參數一:attr:線程屬性結構體指針

1403             參數二:detachstate(傳出參數): PTHREAD_CREATE_DETACHED(分離);PTHREAD_CREATE_JOINABLE(分離);

1404             返回值:成功;0; 失敗:錯誤號;

1405         2)int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);    設置線程分離狀態。

1406

1407     4.線程棧地址:

1408         int pthread_attr_getstack(pthread_attr_t *attr, void **stackaddr, size_t *stacksize);    獲取線程棧地址

1409         參數一:attr:        線程屬性結構體指針

1410         參數二:stackaddr:(傳出)    獲取線程棧地址

1411         參數三:stacksize:(傳出)    獲取線程棧大小。

1412         返回值:成功;0;失敗:錯誤號。

1413         int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize); 設置線程棧地址

1414

1415     5.線程棧大小

1416            int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);獲取線程棧大小

1417

1418         int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); 設置線程棧大小

1419         參數一:attr:        線程屬性結構體指針

1420         參數二:stacksize:    設置線程棧大小

1421         返回值:成功;0;失敗:錯誤號。

1422

1423

1424 五。線程使用注意事項

1425     1.退出線程應使用 pthread_exit();

1426     2.避免殭屍線程的產生:

1427         1)pthread_join(); 回收子線程。

1428         2)pthread_detach();分離線程。

1429         3)指定分離屬性,再pthread_create();建立線程。

1430     3.線程共享進程地址空間:malloc和mmap內存可被其餘線程釋放。

1431     4.多線程中應避免使用fork(),除非立刻exec;多線程fork()後,產生的進程中只含有調用fork函數的線程,其餘線程均退出。

1432     5.線程主函數中,應該避免返回局部變量地址值。

1433     6.避免多線程和信號混用。

1434

1435

1436

1437 "===線程同步、進程同步========================================================================================================================"

1438 一。同步、線程同步概念

1439     1.生活中的同步爲: 同時起步,協調一致。

1440     2.線程中的同步爲: 協同步調,指定訪問數據的前後順序。

1441     3.全部多個控制流,共同操做同一共享數據的場景,都須要同步機制。

1442     4.數據混亂的緣由:(產生與時間有關的錯誤)

1443         1)資源共享(獨享資源則不會)

1444         2)調度隨機

1445         3)線程間缺少必要的同步機制

1446             其中前二者不可改變,這是多線程併發得以實行的必要條件,那麼就須要在線程間加上同步機制。

1447

1448 二。線程同步的方法

1449     1.互斥量(互斥鎖:mutex)------》建議鎖(協同鎖)

1450         1)互斥量特徵

1451             1)建議鎖,不具備強制性。

1452             2)訪問共享數據前,加鎖,訪問結束後當即解鎖。

1453             3)線程不按規則訪問數據依然能夠成功(即不加鎖訪問);但數據會混亂。

1454

1455         2)一系列操做函數

1456             1)初始化互斥鎖

1457                 1)動態初始化:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

1458                     pthread_mutex_t 互斥鎖的類型,本質是一個結構體,只有 0 和 1 兩個值。

1459                     參數一:互斥鎖,

1460                     參數二:互斥鎖的類型(進行修改,能夠在進程間使用。)

1461                     restrict:關鍵字;只用於限制指針:告訴編譯器,全部修改該指針指向內存中的操做,只能經過本指針完成;

1462                                         不能經過本指針以外的其餘變量和指針操做。

1463                 2)靜態初始化:pthead_mutex_t muetx = PTHREAD_MUTEX_INITIALIZER;

1464

1465             2)加鎖:

1466                 int pthread_mutex_lock(pthread_mutex_t *mutex);

1467                 可理解爲將 mutex--;

1468                 說明:嘗試加鎖,若是加鎖不成功,線程阻塞,阻塞到持有該互斥量的其餘線程解鎖爲止。

1469             3) 解鎖:

1470                 int pthread_mutex_unlock(pthread_mutex_t *mutex);

1471                 可理解爲將 mutex++;

1472                 說明:主動解鎖,同時將阻塞在該鎖上的全部線程所有喚醒;至於哪一個線程先被喚醒,取決於優先級、調度。默認:先阻塞、先喚醒。

1473             4)    嘗試加鎖

1474                 int pthread_mutex_trylock(pthread_mutex_t *mutex);

1475                 說明: lock加鎖失敗會阻塞,等待所釋放;  trylock:加鎖失敗直接返回錯誤號,不阻塞;

1476             5)銷燬互斥鎖

1477                 int pthread_mutex_destroy(pthread_mutex_t *mutex);

1478                 說明:程序結束時,要銷燬使用的互斥鎖。

1479         "在訪問共享資源前加鎖,訪問結束後當即解鎖,鎖的 粒度 越小越好。"

1480

1481     2.死鎖--------------------不是線程同步的一種方式,而是一種現象。

1482         1)死鎖一。(對同一個互斥量加鎖兩次。)

1483             連續加鎖,阻塞等待。

1484             示例:

1485     pthread_mutex_t mutex;                        //定義一個全局互斥鎖變量。

1486     void *do_sth(void* arg)

1487     {

1488         srand((unsigned int) time(NULL));

1489         while(1)

1490         {

1491             pthread_mutex_lock(&mutex);            //子線程加鎖

1492             printf("hello ");

1493             sleep(rand()%3);

1494             printf("world\n");

1495             pthread_mutex_unlock(&mutex);        //子線程解鎖

1496         }

1497

1498         pthread_exit(NULL);                            //結束子線程

1499     }

1500     int main(void)

1501     {

1502         pthread_t ptid;

1503         srand((unsigned int) time(NULL));                //隨機數的種子

1504         pthread_mutex_init(&mutex, NULL);                //互斥鎖動態初始化

1505

1506         pthread_create(&ptid, NULL, do_sth, NULL);        //建立子線程

1507         while(1)

1508         {

1509             pthread_mutex_lock(&mutex);        //主控線程第一次對數據加鎖

1510

1511             printf("HELLO ");

1512             sleep(rand()%3);                //這個睡眠額度做用是:即便此時CPU空出來,但因爲另外一個線程沒有拿到鎖,仍是沒法進行輸出。

1513             printf("WORLD\n");  

1514             pthread_mutex_lock(&mutex);     //死鎖:對同一互斥量連續加鎖兩次/屢次;形成線程阻塞。

1515             pthread_mutex_unlock(&mutex);   //數據操做完後當即解鎖,使鎖的粒度最小。

1516         }

1517         pthread_mutex_destroy(&mutex);        //程序結束,銷燬使用的互斥鎖。

1518         pthread_join(ptid, NULL);            //回收子線程。

1519          pthread_exit(NULL);                    //主控線程退出

1520     }

1521

1522         2)死鎖二。(多個共享數據,多把鎖。持有鎖A的線程1請求鎖B,持有鎖B的線程2請求鎖A)

1523                     更極端的狀況:震盪。

1524                 解決方法:    1.當沒法獲取全部鎖的時候,放棄已經掌握的鎖

1525                               2.規定 不一樣線程 獲取 共享數據 的順序(即規定獲取鎖的順序)。

1526

1527     //兩組共享的數據及其配套鎖

1528     typedef struct recond_m

1529     {

1530         int data_m;

1531         pthread_mutex_t mutex_m;

1532     }recond_m;

1533

1534     typedef struct recond_n

1535     {

1536         int data_n;

1537         pthread_mutex_t mutex_n;

1538     }recond_n;

1539

1540     recond_m data_1;                                    //定義的兩個全局共享變量

1541     recond_n data_2;   

1542     void *do_sth(void* arg)                                //子線程執行邏輯

1543     {

1544         srand((unsigned int) time(NULL));                //隨機數的種子

1545         while(1)

1546         {

1547             //加鎖順序: 先 data1, 再data2;

1548             pthread_mutex_lock(&data_1.mutex_m);

1549             data_1.data_m = 9;                            //對全局變量修改

1550             printf("zi xian data_m:%d\n ",data_1.data_m);

1551             pthread_mutex_lock(&data_2.mutex_n);       

1552             data_2.data_n = 9;

1553             printf("zi xian data_n:%d\n ",data_2.data_n);

1554

1555             pthread_mutex_unlock(&data_2.mutex_n);        //解鎖兩個共享數據

1556             pthread_mutex_unlock(&data_1.mutex_m);

1557         }

1558

1559         pthread_exit(NULL);

1560     }

1561

1562     int main(void)

1563     {

1564         pthread_t ptid;

1565         srand((unsigned int) time(NULL));

1566         //動態初始化兩把鎖

1567         pthread_mutex_init(&data_1.mutex_m, NULL);

1568         pthread_mutex_init(&data_2.mutex_n, NULL);

1569

1570         pthread_create(&ptid, NULL, do_sth, NULL);            //建立子線程

1571         while(1)

1572         {

1573             //主控線程 : 先鎖 data2; 再鎖data1;

1574             pthread_mutex_lock(&data_2.mutex_n);

1575             data_2.data_n = 6;

1576             printf("zhu kong data_n:%d\n ",data_2.data_n);

1577             sleep(1);                                        //空出CPU資源, 子線程加鎖。

1578             pthread_mutex_lock(&data_1.mutex_m);

1579             data_1.data_m = 9;

1580             printf("zhu kong data_m:%d\n ",data_1.data_m);

1581

1582             pthread_mutex_unlock(&data_1.mutex_m);

1583             pthread_mutex_unlock(&data_2.mutex_n);

1584            

1585         }

1586

1587         pthread_mutex_destroy(&data_1.mutex_m);

1588         pthread_mutex_destroy(&data_2.mutex_n);

1589         pthread_join(ptid, NULL);

1590         pthread_exit(NULL);

1591     }

1592

1593     2.讀寫鎖(讀寫鎖只有一把)

1594         1)讀寫鎖特性

1595             1.寫獨佔,讀共享。

1596             2.寫鎖的優先級高於讀鎖。

1597             "詳解:三種狀況"

1598                 1)寫模式加鎖:解鎖前,全部對該鎖加鎖的進程都會被阻塞。

1599                 2)讀模式加鎖,解鎖前,若是其餘全部線程以讀模式加鎖會成功,以寫模式加鎖會失敗。

1600                 3)讀模式加鎖,解鎖前,其它線程中既有寫模式加鎖,也有讀模式加鎖,全部線程阻塞;解鎖後,優先知足寫模式的加鎖。

1601

1602         2)一系列操做函數

1603             就不贅述了;和上述同樣。

1604         3)使用場景:

1605             適合於對數據結構讀的次數遠大於寫的次數。

1606

1607         3)讀寫鎖優勢:

1608             當讀線程 多於 寫線程時,能夠提升數據的訪問效率。

1609

1610     3.條件變量

1611         1)條件變量的特性

1612             1.條件變量自己不是鎖,可是依然能夠形成線程阻塞;一般與互斥鎖配合使用。

1613            

1614         2)一系列操做函數(拿出其中的三個特殊函數)

1615             int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

1616             說明:阻塞等待一個條件變量。隱喻着在此函數調用前,數據已完成加鎖操做;pthread_mutex_lock(&mutex)。

1617             該函數有三步:

1618                 1)阻塞等待條件 cond 知足;

1619                 2) 條件未知足時,解鎖已經得到的鎖。

1620                 3)當條件知足時,被喚醒,接觸阻塞再次嘗試加鎖互斥量。爲一個原子操做。

1621

1622             int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);

1623             說明:指定時間後嘗試調用該函數。符合條件則運行;不符合條件,不阻塞,返回錯誤號。

1624             參數三:絕對時間。

1625

1626             int pthread_cond_signal(pthread_cond_t *cond);

1627             喚醒至少一個阻塞在條件變量上的線程。(實際上也就只喚醒一個,可是man手冊中,沒有這樣寫)

1628             int pthread_cond_broadcast(pthread_cond_t *cond);

1629             喚醒所有阻塞在該條件變量上的線程。

1630

1631         3)生產者、消費者模型

1632                 生產者線程:

1633                 消費者線程:

1634                 公共區(共享資源):

1635                 對公共區添加條件變量,互斥鎖,對數據加以保護。

1636        

1637         4)條件變量的優勢:

1638             相較於直接使用互斥量,使用它只有當條件知足時,各線程纔會競爭,提升了程序間的效率。

1639

1640     4.信號量 -------》本質:結構體。

1641         1)特性:

1642                 1.進化版的互斥鎖。。(1-> N);

1643                 "2.信號量的初值,決定了佔用信號量的線程的個數。    "

1644         2)一系列操做函數

1645             1)int sem_init(sem_t *sem, int pshared, unsigned int value);

1646                 說明:初始化一個信號量

1647                 參數一:信號量的指針。

1648                 參數二:pshared 取0用於線程間,取非0 用於進程間.

1649                 "參數三:信號量的初值。"

1650             2)int sem_destroy(sem_t *sem);

1651                 說明:銷燬一個信號量

1652             3)int sem_wait(sem_t *sem);        (類比pthread_mutex_lock());

1653                 說明:信號量加鎖--。

1654                 詳細:信號量大於0,則信號量--;  信號量等於0,則線程阻塞等待。

1655             4) int sem_post(sem_t *sem);        (類比pthread_mutex_unlock());

1656                 說明:信號量解鎖++;

1657                 詳細:信號量小於最大值,則信號量++;信號量等於最大值,則線程阻塞等待。

1658             5)int sem_trywait(sem_t *sem);

1659                 說明:信號量嘗試加鎖,不阻塞。

1660             6)int sem_timedwait(sem_t *sem, const struct timespec *abc_timeout);

1661                 說明:指定時間後嘗試對信號量加鎖,成功則運行,不成功,返回錯誤號,不阻塞。

1662                 參數二:絕對時間。

1663                 例子:定時1秒; time_t cur = time(NULL);    //獲取當前時間。

1664                                 struct timespec t_time;        //定義結構體變量

1665                                 t_time.tv_sec = cur + 1;    //定時1秒

1666                                 t_time.tv_nsec = 0;

1667                                 sem_timedwait(&sem, &t_time);

1668                                

1669         3)生產者、消費者模型

1670

1671 三。進程間同步

1672     1.信號量

1673         1.

1674     2.互斥量(mutex)

1675         1.進程間也可使用互斥鎖,來達到同步的目的。可是在初始化以前,應該修改一下其屬性。

1676         2.屬性修改函數:

1677             pthread_mutexattr_t mattr 類型;        用於定義mutex鎖的 屬性。

1678             int pthread_mutexattr_init(pthread_mutexattr_t *mattr)  函數;    初始化一個mutex屬性對象;

1679             int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)    函數;     銷燬mutex屬性對象,(非銷燬鎖);

1680             int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);    修改mutex屬性。

1681             參數二:pshared取值:

1682                 線程鎖:PTHREAD_PROCESS_PRIVATE (mutex 的默認屬性即爲線性鎖,進程間私有)

1683                 進程鎖:PTHREAD_PROCESS_SHARED

1684

1685     3.文件鎖

1686         int fcntl(int fildes, int cmd, ...);函數;

1687         參數一:文件描述符;

1688         參數二:

1689                 F_SETLK(struct flock*) 設置文件鎖 (trylock);;

1690                 F_SETLKW(struct flock*)設置文件鎖 (lock)W -->wait;

1691                 F_GETLK(struct flock*) 獲取文件鎖  ;

1692

1693         參數三:struct flock 結構體內容;

1694                 1)l_type:  鎖的類型: F_RDLCK(讀鎖);  F_WRLCK(寫鎖);  F_UNLCK(解鎖);

1695                 2)l_whence:偏移位置:SEEK_SET;  SEEK_CUR;  SEEK_END;

1696                 3) l_start: 起始偏移:

1697                 4) l_len:    長度 ; 0 表示整個文件加鎖。

1698                 5)l_pid;    持有該鎖的進程ID;  僅限F_GETLK中使用。

1699

1700

1701 "===線程========================================================================================================================"

1702

1703

1704 "===網絡編程========================================================================================================================"

1705

1706

1707 "===網絡編程之理論基礎========================================================================================================================"

1708

1709 一。協議概念

1710     1.協議:

1711

1712     2.典型協議:

1713         傳輸層:     常見協議:TCP / UDP;

1714         應用層:     常見協議:HTTP; FTP;

1715         網絡層:     常見協議:IP; ICMP; IGMP;

1716         網絡接口層:常見協議:ARP; RARP;

1717

1718         ARP協議:正向地址解析協議,經過已知的IP,尋找對應主機的MAC地址。

1719         RARP協議:反向地址轉換協議,經過MAC地址肯定IP地址。

1720         FTP :文件傳輸協議

1721         TCP :傳輸控制協議;是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議。

1722         UDP:用戶控制協議,是OSI參考模型中一種無鏈接的傳輸層協議,提供面向事物的簡單不可靠信息傳送服務。

1723         IP:因特網互聯協議

1724         HTTP:超文本傳輸協議,是互聯網上應用最普遍的一種網絡協議。

1725         ICMP:Internet控制報文協議,是TCP/Ip協議族的一個子協議,用於IP主機和路由器之間傳遞消息。

1726         IGMP:Internet組管理協議,運行在主機和組播路由器之間。

1727

1728 二。B/S ; C/S 模型結構【即網絡應用層設計模式】

1729     1.C/S模型:(客戶機/服務器模式)

1730         如:實際應用:QQ;

1731         兩個數據端:客戶端(client)/服務器(server);

1732         該模型的優勢:

1733                 1.緩存數據到本機,提升通訊效率。

1734                 2.協議的選擇靈活。-------自定義協議,或者對現有協議進行裁剪。

1735         該模型的缺點:

1736                 1.對用戶而言,安全性較低(由於在用戶端安裝了應用程序(即客戶端))。

1737                 2.開發量大。

1738                 3.受操做平臺限制。

1739         使用場景:

1740                 1.當須要自定義協議

1741                 2.對數據要求高。

1742

1743     2.B/S模型:(瀏覽器/服務器模式)

1744         藉助瀏覽器完成通訊,用戶不須要在主機上安裝應用程序。如(當年的偷菜遊戲,即網頁遊戲。)

1745         該模型的優勢:

1746                 1.不受操做平臺限制;

1747                 2.開發量小

1748

1749         該模型的缺點:

1750                 1.由於數據不能緩存到本地,因此大型的網絡遊戲不能使用。

1751                 2.協議選擇相對來講不太靈活。(瀏覽器的開發要求必須知足)。

1752

1753         使用場景:

1754                 1.對數據要求不過高,

1755                 2.跨平臺方便的

1756

1757

1758 三。分層模型"【重點, 必須掌握】"

1759     1.OSI 七層模型

1760         物數網傳會表應:【物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。】

1761

1762     2.TCP/IP 4層模型

1763         網網傳應:【網絡接口層(由物理層和數據鏈路層組成,也有人叫作數據鏈路層)、網絡層、傳輸層 、應用層】。

1764         4層模型與7層模型,互相對應。

1765         網絡接口層協議:ARP協議和RARP協議。        網絡層協議:IP協議、ICMP協議、IGMP協議。

1766         傳輸層協議:TCP/UDP協議(主要是這兩種);   應用層協議:HTTP協議、 FTP協議。

1767         TCP 是一種面向鏈接的、可靠的協議,有點像打電話。也就是說TCP傳輸的雙方首先要創建聯接,以後由TCP協議保證數據收發的可靠性,數據包丟失重發。

1768         UDP是無鏈接的傳輸協議,不保證可靠性,有點像寄信。使用UDP協議的應用程序須要本身完成丟包重發、消息排序等工做。

1769

1770 四。協議格式

1771     1.數據包的封裝【網絡環境中數據通訊過程】。

1772         1)(((((數據)應用層)傳輸層)網絡層)數據鏈路層);

1773         數據包裝完後,才能夠在網絡上進行傳輸;

1774

1775         2)傳輸層及其如下由內核控制,應用層由用戶控制。不一樣主機之間,數據在網絡中的發送,應用層數據經過協議棧發到網絡上時,每層協議都要加上一個數據首部,稱爲封裝。

1776

1777     2.以太網幀格式:

1778         ARP數據報格式;  藉助 IP----》獲取mac地址。

1779         目的地址,源地址,類型, 數據, CPC(校驗碼)。

1780         其中 源地址和目的地址是 網卡的硬件地址(即MAC地址),長度是48位;

1781

1782         2)以太網幀中數據長度最小爲46字節,最大爲1500字節。

1783

1784

1785     2.IP段格式

1786         4位首部長度, 4位版本號, 16位總長度, 8位TTL(記錄數據包的跳數), 32位源IP, 32位目的IP。

1787        

1788

1789     3.TCP數據包格式:(面向鏈接的,複雜)

1790         16位源端口號, 16位目的端口號。 4位首部長度,6位標誌位; 16位窗口大小; 32位序號; 32位確認序號。

1791

1792     4.UDP數據包格式     (無鏈接的)

1793         16位源端口號; 16位目的端口號。  最大包括:2^16 = 65535;

1794         端口號:在一臺主機上惟一標識一個進程。    != pid; 應用與網絡

1795         IP地址:在網絡中惟一標識一臺主機。

1796         IP地址+端口號; 在網絡環境中惟一標識一個進程。------》socket

1797

1798         HTTP 服務默認 TCP 協議的 80 端口;

1799         FTP 服務默認 TCP協議的 21 端口;

1800         TFTP 協議默認 TCP協議的 69 端口。 

1801        

1802     5.NET映射機制:映射表

1803         1.私有IP:僅在局域網有效。        (容許重複)

1804         2.公網IP:在整個網絡環境可見。    (不容許重複,即衝突)

1805         3.路由器內部,NAT映射表。藉助私有IP和端口號 -------- 共有IP和標號。

1806

1807     6.打洞機制:

1808         藉助 公網服務器, 將兩臺私有IP的主機,直接相連,完成數據的直接傳遞。

1809

1810 五。TCP 的3次握手創建鏈接、4次握手斷開鏈接。"【重點】"

1811     三次握手創建鏈接:

1812         主動發起鏈接一方,發送請求:SYN(請求創建鏈接); 

1813         被動接受連接一方,回覆:ACK(應答),SYN(); 

1814         主動發起連接一方,回覆:ACK(應答,創建鏈接成功);

1815

1816     四次握手斷開鏈接:

1817         主動關閉鏈接一方1: FIN

1818         被動關閉鏈接一方1: ACK

1819         主動關閉鏈接一方2: FIN

1820         被動關閉鏈接一方2: ACK

1821

1822 mss(最大報文長度): 與下面的MTU大小相關。

1823    

1824 六。MTU概念

1825     MTU:最大傳輸單元。

1826         在以太網幀格式中爲 1500 字節。

1827     (MTU - 數據報頭)= mss ;

1828    

1829 七。滑動窗口

1830     給對端提供一個發送數據的總上限值。---------》進行流量控制

1831     最大:65535;由於:在報頭中佔據16位。

1832

1833 八:TCP協議格式:

1834     16位源端口, 16位目的端口,32位序列號, 32位確認序列號, 16位窗口大小, 標誌位(SYN, ACK, FIN);

1835     須要記住使用的就上面這些;

1836    

1837 九。TCP狀態轉換圖:"【重點】"

1838

1839

1840

1841 十:2MSL

1842         1)查看:net

1843

1844

1845 十一。端口複用:

1846

1847 十二:半關閉:

1848         1)主動關閉連接一方,處於FIN_WAIT_2.  4次握手---完成兩次。

1849         2)

1850 "===UDP======================================"

1851 1.UDP 協議格式

1852     主要針對不穩定的網絡層,作傳輸行爲。  TCP--徹底彌補 97% ;UDP---徹底不彌補。

1853     TCP 和UDP 優缺點:

1854         網絡中TCP一次傳輸的多組數據路徑是相同的(若是網絡中的路由器沒有發生變化);

1855         網絡中UDP一次傳輸的多組數據路徑是不一樣的(致使:)。

1856        

1857         TCP:面向鏈接的可靠數據傳輸。---類比打電話

1858             優勢:  1.數據傳輸可靠;;

1859                     2.穩定:數據內容穩定,流量穩定(mss, 滑動窗口),速率穩定(即線路穩定,在網絡中通過相同的路由)。

1860             缺點:  1.效率低,開銷大。

1861                     2.速度慢,(由於每次數據傳輸過去,須要對方回覆)

1862            

1863             應用場景:重要文件、大文件。

1864

1865         UDP:無鏈接的不可靠報文傳遞。-----類比發短信           

1866             優勢:  1.速度快

1867                     2.實時性高,效率高。

1868             缺點:  1.數據傳輸不可靠。

1869                     2.穩定性差(每次傳輸的路徑不同)。

1870

1871             應用場景:對實時性要求較高:視頻聊天、視頻電話、分屏廣播。

1872

1873         騰訊:開始:TCP ---後來TCP+UDP(作判斷,看適合用哪一種);----後來UDP+應用層校驗(不丟失數據包)--(這種方式須要自行開發應用層協議。)

1874

1875 2.UDP C/S 服務器模型

1876     比較差別

1877     TCP:  三次握手創建鏈接---socket();bind(); accept();read();小寫轉大寫;write();-----service端

1878                             -------socket(); connect();write(); read();

1879     UDP:    無需創建連接---socket(); bind(); recvfrom();

1880

1881         UDP默認狀況下支持 多路IO---高併發服務器。

1882         1.爲了使支持狀況更好,須要應用層本身封裝校驗;

1883         2.擴大接收端緩存區大小。使用 setsockopt();

1884

1885     注意:send(), recv() 只能用於TCP連接的C/S模型。

1886    

1887 3.UDP 廣播

1888

1889 4.UDP 組播

1890

1891 "上課所用的分屏軟件的設計思想:"

1892 server端:

1893     1)服務器端:截屏模塊,截取本地屏幕數據。獲得圖片,(保證人眼的觀看,須要1秒24幀)幾M。

1894     2)降幀12幀;保證數據發送效率。

1895     3)選用適當的算法進行壓縮。 幾十KB

1896     4)爲進一步提升效率,只將有變化、改動、座標區域,截取,壓縮,發送。

1897

1898 client端:

1899     1)每臺接收的主機 有個客戶端,使用和服務器端相同的端口。

1900     2)接收到數據後以相同的算法,逆方式解壓縮。

1901

1902 5.本地套接字:

1903     IPC的一種方法:

1904

1905 6.經常使用的開源庫(網絡編程)

1906     1.libevent

1907     2.libv

1908 7.服務器壓力測試開源庫

1909

1910 8.使用軟件:

1911     wareshark;

1912

1913 "===UDP======================================"

1914

1915

1916

1917

1918 "===網絡編程之理論基礎========================================================================================================================"

1919

1920

1921 "===網絡編程之 socket(套接字) 編程========================================================================================================================"

1922     在網絡通訊中,socket通訊時必定是成對出現的。

1923     使用的時候必需要指定:IP和端口號 ;socket = IP+port(端口號);

1924

1925 一。理論基礎:

1926     1.網絡字節序

1927         大端法:高位存低地址。

1928         小端法:高存高。(x86結構,即我的電腦;微軟的主推)

1929

1930         網絡環境中:--------》網絡字節序:大端法。

1931         本地環境中:--------》本機字節序:小端法。

1932         因此網絡中傳輸的數據須要進行字節序轉換。

1933         "一套操做函數:";

1934         uint32_t htonl(uint32_t hostlong); ----本地--轉--網絡-- 32; --->IP 地址

1935

1936            uint16_t htons(uint16_t hostshort); ----本地--轉--網絡-- 16; --->port號(端口號)

1937

1938            uint32_t ntohl(uint32_t netlong);  ----網絡--轉--本地--32;   

1939

1940            uint16_t ntohs(uint16_t netshort);----網絡--轉--本地--16;

1941

1942     2.IP地址轉換

1943         由於本地的IP地址爲字符串型,適合人類查看。

1944         網絡上的IP爲 unsigned int 型。

1945         str IP <-----> 網絡字節序IP

1946         int inet_pton(int af, const char *src, void *det );

1947             af:      ipv4:AF_INET;

1948                   ipv6:AF_INET6;

1949

1950             src:  網路字節序的IP地址;

1951

1952             det:  用來儲存轉化後的IP地址。

1953

1954

1955         const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

1956

1957             af:  ipv4: AF_INET;

1958

1959                  ipv6: AF_INET6;

1960

1961             src:網絡字節序的IP地址。

1962

1963             dst:用來存儲轉化後的IP地址。

1964

1965             size: dst的大小。

1966            

1967

1968     3.socketaddr地址結構

1969         定義變量: struct sockaddr_in  saddr;

1970

1971         初始化:

1972

1973                struct sockaddr_in {

1974                sa_family_t    sin_family; /* address family: AF_INET */

1975                in_port_t      sin_port;   /* port in network byte order */

1976                struct in_addr sin_addr;   /* internet address */

1977             };   

1978

1979 二。C/S模型實現的 TCP 客戶端服務器程序"【重點, 必須掌握】"

1980     socket----套接字:

1981         本質:內核緩衝區(發送,接收。)

1982         "進行通訊的時候,是成對出現的。雙向全雙工"

1983

1984     1.建立一個套接字:

1985            SOCK_DGRAM --------報式協議        UDP 協議

1986     protocol:0 流式默認: TCP

1987                 報式默認: UDP

1988     返回值:成功則指向新建立的socket的文件描述符; 失敗:返回-1,設置errno.

1989

1990     2.int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);綁定服務器的:IP, port(端口號);到套接字上。

1991         參一:sockfd :socket文件描述符。

1992         參二:構造出IP地址+端口號;(sockaddr_in 類型)

1993         參三:地址的長度。

1994

1995     3. int listen(int sockfd, int backlog); 設置同時向服務器發起三次鏈接的客戶端數量(注意:不是客戶端連接服務器的數量)  -- 10    ;

1996         參一:socket函數的返回值(即socket文件描述符)

1997         參二:數量上限。

1998         注意:這個函數的做用是:指定鏈接數的,而不是等待客戶端鏈接的。

1999

2000     4.int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);  阻塞等待客戶端發起鏈接請求。

2001         參一:socket函數的返回值(即socket文件描述符)

2002         參二:addr:傳出參數。返回客戶端的地址結構(IP、port)。

2003         參三:addrlen:傳入、傳出參數。

2004         返回值:返回一個新的fd,指向客戶端的套接字。

2005

2006     5.int connect(int sockfd, const struct aockaddr *addr, socklen_t addrlen);

2007         參一:socket函數的返回值(即socket文件描述符)

2008         參二:傳入參數,指定服務器端地址信息,含IP地址和端口號。

2009         參三:傳入參數:地址的大小。

2010         返回值:成功;0;失敗:-1。

2011

2012

2013 三。服務器、客戶端封裝錯誤處理模塊。

2014    

2015     封裝思想:

2016         將系統調用進行 淺封裝;

2017         簡化程序邏輯 ------首字母大寫-------能夠直接從代碼編寫頁面進入 man page。

2018

2019

2020     read返回值:

2021

2022         > 0:   返回實際讀到的字節數

2023

2024         == 0:  到達文件末尾。或者管道對端關閉。或者套接字對端關閉。

2025

2026         < 0 (-1):

2027

2028             1. errno == EINTR  ( ECONNABORTED 網絡中)

2029

2030                 慢速系統調用,被信號中斷。 應該設置重啓。

2031

2032             2. errno == EAGIAN (或 EWOULDBLOCKED)

2033

2034                 待讀對象設置非阻塞讀,而且此刻沒有數據到達。 應該設置從新讀取。

2035

2036             3. error

2037                 perror();  exit();

2038     readn

2039

2040     readline

2041

2042

2043 四。多進程併發服務器

2044     1. 流程: socket() bind()  listen() accept() read ()  write()  close();

2045         詳解: 1.建立套接字;  2.定義地址變量,給他賦值IP、port; 3.監聽客戶端鏈接請求。  4.在循環阻塞等待連接客戶端,一旦有客戶端鏈接成功,就建立子進程。

2046                 5.子進程負責與客戶端通訊; 6.父進程 繼續阻塞等待客戶端的連接; 同時註冊信號,回收子進程。

2047

2048     2. 子進程用來跟客戶端通訊。―― fork()

2049

2050     3. 父進程。 監聽客戶端鏈接請求。 註冊信號捕捉函數,回收子進程。

2051

2052     4. while (1 ) {

2053

2054         fd = accept()

2055

2056         fork(); 

2057        }

2058

2059

2060

2061 五。多線程併發服務器

2062    

2063     1. socket() bind()  listen() accept() read ()  write()  close();

2064         詳解:1.建立套接字; 2.定義地址變量,給他賦值IP、port; 3。監聽客戶端鏈接請求;  4.在循環中,主控線程阻塞等待客戶端的連接,一旦有客戶端鏈接成功,就建立子線程,同時分離或專門用一個子線程回收剩餘的子線程。

2065                 5.主控線程負責 繼續阻塞等待客戶端鏈接, 6.子線程負責與客戶端通訊。

2066

2067     2. 子線程用來跟客戶端通訊。―― pthread_create();

2068

2069     3. 主線程。  監聽客戶端鏈接請求。 子線程1 :pthread_join(); pthread_detach();---修改線程。

2070

2071     4. 客戶端通訊---小寫--大寫: 子線程的主控函數。

2072

2073 六:多路I/O轉接

2074

2075     1.select【*】

2076         1)一組函數

2077

2078         2)監聽、轉換,實現方法、思想

2079

2080         3)創建流程: socket()  setsockopt()  bing()  listen()  fd_set集合的賦值  select()  FD_ISSET()

2081             accept()   符合條件的描述符通訊。

2082

2083     2.poll

2084         1)一組函數

2085         2)監聽、轉換,實現方法、思想

2086         3)區別poll、select比較,優缺點;

2087

2088     3.epoll【**】

2089         1)一組函數

2090         2)監聽、轉換,實現方法、思想

2091         3)區別poll、select、epoll比較,優缺點;;

2092

2093 七。epoll多路IO轉接模型

2094     1.設置突破1024文件描述符限制

2095     2.epoll操做函數

2096         epoll_create();

2097         epoll_ctl();

2098         epoll_wait();

2099     3.epoll實現多路IO轉接模型;

2100 八.epoll

2101

2102

2103 "===網絡編程之 socket 編程========================================================================================================================"

2104

2105

2106 "===網絡編程

相關文章
相關標籤/搜索