1 string 字符串操做 2 3 4 操做數的都是 ( char * )型,操做數必須是指向字符串的指針("a"),不能是字符('a'),操做時不考慮末尾的'\0'。 5 6 size_t strlen( const char *s ); 字符串求長,返回字符串或指針的實際大小,和 sizeof() 不一樣,好比建立字符數組 strlen 只返回其中字符串的大小,不包括 '\0' 7 char *strrev( char *s ); 字符串反轉,不包括 NULL 8 char *strcpy( char *dest, const char *src ); 字符串複製, dest 必須有足夠的空間來容納 src 的字符串, dest 空間不夠時結果是爲定義的(結果顯示增大了空間去容納 src 的字符),dest 不能是字符指針 9 int atoi( const char *nptr ); 字符串轉化爲整數 10 char *strcat( char *dest, const char *src ); 字符串鏈接 11 int strcmp( const char *s1, const char *s2 ); 字符串比較,區分大小寫 12 int strcasecmp(const char *s1, const char *s2); 不區分大小寫比較,在頭文件 strings.h 中,可在字符串指針和字符數組之間相互比較,注意地址範圍 13 int strncasecmp(const char *s1, const char *s2, size_t n); 不區分大小寫比較,只比較 s1 前 n 個字符 14 char *strchr( const char *s, int c ); 查找字符,返回首次出現 c 的位置的指針,若是 s 中不存在 c 則返回 NULL 15 void bzero(void *s, size_t n); 將字符串 s 中前 n 個( 0 - n-1 )字符設爲 '\0', strings.h 中 16 17 18 19 void perror(const char *s); 20 sprintf( buf, "hello world! %s\n", string ); 將字符串寫到 buf 中,而不是標準輸出 21 int scanf(const char *format, ...); 成功返回讀取到是字符數,失敗返回 EOF,目標是指針(數組指針)時不用 "&" 22 int fscanf( FILE *stream, const char *format, ... ); 從文件流中讀取一個單詞,不包含空格,讀取的內容存到字符數組裏,以 '\0' 結尾 23 int sscanf(const char *str, const char *format, ...); 24 int vscanf(const char *format, va_list ap); 25 int getc(FILE *stream); 從文件流中讀取一個字符 26 int getchar(void); 從標準輸入中讀取一個字符,用 ASCII 碼將字符轉換爲 int 27 char *gets(char *s); 從 stdin 中讀取一行放入 s 中,只到遇到 EOF 或者 newline 28 int fgetc(FILE *stream); 29 char *fgets(char *buffer, int size, FILE * stream); 從文件中讀取一行或指定個數的字符; buffer 爲緩衝區,用來保存讀取到的數據; size 爲要讀取的字符的個數。若是該行字符數大於size-1,則讀到 size-1 個字符時結束,並在最後補充' \0';若是該行字符數小於等於 size-1,則讀取全部字符,並在最後補充 '\0'。即,每次最多讀取 size-1 個字符。讀取的字符包括換行符; stream 爲文件指針 30 31 32 33 文件 I/O 編程 34 35 36 int open( const char *pathname, int oflag [, mode_t mode ] ); pathname 是打開或建立文件的全路徑名; oflag 由 O_RDONLY O_WRONLY O_ROWR 中的一個和 O_APPEND(每次寫都追加到文件尾) O_CREAT(文件不存在就建立他,須說明第三個參數) O_EXCL(若是指定了 O_CREAT 而文件已存在則出錯) O_TRUNC(文件存在且由寫權限,則將其長度截爲 0) O_NOCTTY(若是 pathname 指的是終端設備,則不將此設備分配做爲此進程的控制終端) O_NONBLOCK(若是打開的是一個 fifo 、塊特殊文件或字符特殊文件則本次打開和後續 I/O 操做設爲非阻塞) O_SYNC(使每次 write 都等到物理 I/O 操做完成) 中的一個或多個進行「 | 」運算構成; mode 只有建立文件時才使用,權限設置;失敗返回 -1 37 int creat( const char *pathname, mode_t mode ); 建立文件,以只寫方式打開,失敗返回 -1 38 ssize_t read( int fd, void *buf,size_t count ); buf 不能是字符指針,通常爲字符數組名; count 是 指望讀取的最大字節數,一個漢字佔 3 個字節(linux);返回 0 時標是讀到文件尾; 39 ssize_t write( int fd, const void *buf, size_t count ); 若是讀寫的大小 count 超出了給出字符串的大小不會出錯,讀文件後不會刪除內容 40 int close( int filedes ); 進程結束內核會自動關閉打開的文件 41 off_t lseek (int filesdes, off_t offset, int whence ); 設置文件讀寫位置;文件偏移量,默認爲 0(除非指定 O_APPEND); off_t 至關於 signed int(typedef),可正可負; whence 爲 SEEK_SET 距文件開始處 offset 個字節, SEEK_CUR 當前值加 offset 字節, SEEK_END 是文件尾 ;成功返回新的文件位移,失敗返回 -1 42 43 FILE *fopen(const char *path, const char *mode); mode 爲 "r" 表示以只讀放是打開文件, r 只讀, w 只寫, a 追加, t 文本文件(可省略不寫), b 二進制文件,+ 讀和寫;凡用「r」打開一個文件時,該文件必須已經存在,有 + 時能夠讀寫;用「w」打開的文件只能向該文件寫入,若打開的文件不存在,則以指定的文件名創建該文件,若打開的文件已經存在,則將該文件刪去,重建一個新文件;若要向一個已存在的文件追加新的信息,只能用「a」方式打開文件,若是指定文件不存在則嘗試建立該文件;把一個文本文件讀入內存時,要將ASCII碼轉換成二進制碼,而把文件以文本方式寫入磁盤時,也要把二進制碼轉換成ASCII碼,所以文本文件的讀寫要花費較多的轉換時間,對二進制文件的讀寫不存在這種轉換;標準輸入文件(鍵盤),標準輸出文件(顯示器),標準出錯輸出(出錯信息)是由系統打開的,可直接使用;出錯返回 NULL 44 FILE *fdopen(int fildes,const char * mode); fdopen()會將參數fildes 的文件描述詞,轉換爲對應的文件指針後返回 45 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 46 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 47 int fclose(FILE * stream); 48 49 int fcntl( int fd, int cmd, .../* arg */); 操做文件描述符。 cmd 爲 F_DUPFD,複製一個存在的文件描述符, F_GETFD/F_SETFD,得到/設置文件描述符標誌, F_GETFL/F_SETFL,得到/設置文件描述符屬性(第三個參數爲新設置的文件屬性,只能改變文件的 O_APPEND, O_NONBLOCK, O_SYNC, O_ASYNC 如 flag = flag &~O_APPEND ), cmd = F_GETOWN/F_SETOWN,得到/設置異步 I/O 全部者, F_GETLK/F_SETLK/F_SETLKW,得到/設置文件記錄鎖;失敗返回 -1 50 int ioctl( int fd, int cmd, ...); 串口的波特率等設置,光盤的操做...; ioctl( fd, CDROMEJECT, NULL ) 彈出光驅,用 O_NONBLOCK 打開光驅,由於光驅中可能沒有光盤 51 int select( int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout ); 監控多個文件描述符上是否由輸入輸出或錯誤,處理阻塞方式打開的文件和非阻塞方式打開的文件 select 都是以阻塞方式對待,而不會當即返回; maxfd 是檢測描述符的個數,值應該是最大文件描述符的值 +1; readset 是被監控是否有輸入的文件描述符集,不監控時設爲 NULL,writeset 被監控是否能夠輸出的文件描述符集; exceptset 被監控是否由錯誤產生的文件描述符集; timeval 監控超時時間,設爲 NULL 表示一直阻塞到有文件描述符被監控到有變化;成功返回 3 個集合中有指定變化的文件描述符數目,超時返回 0,失敗返回 -1 52 FD_ZERO( &rset ); 將文件描述符集 rset 的全部位清 0 53 FD_SET( 4, &rset ); 設置文件描述符集 set 的 bit 4 ,監控文件描述符爲 4 的文件( fd_set rfds; FD_SET( 4, rfds ) 54 FD_CLR( fileno( stdin ), &rset ); 將文件描述符集 rset 的 bit 0 置 0 55 FD_ISSET( socketfd, &rset ); 若文件描述符集 rset 的 socketfd 位置 1,返回真,有輸入時就被置 1 56 int poll( struct pollfd fds[], nfds_t nfds, int timeout ); 監控多個文件描述符; nfds 是 fds[] 大小; timeout 是超時時間(毫秒),負值表示沒有超時時間; events 和 revents 中的事件使用 poll.h 中定義的宏來表示, POLLIN 有普通數據可讀, POLLPRI 有高優先級數據可讀, POLLOUT 無阻塞的寫, POLLRDUP TCP 套結字的對端關閉了寫,即不能再讀, POLLERR 出現了錯誤, POLLNVAL 描述符 fd 沒有打開, POLLHUP 掛斷;成功返回 fds 數組中就緒元素個數(該元素的 revents 不爲 0),超時而描述符沒有就緒則返回 0,失敗返回 -1(例 fds[0].fd = 0; fds[0].events = POLLIN; 設置事件 -> fds[0].revents & POLLIN 判斷事件是否發生) 57 int stat( const char *path, struct stat *buf ); 查看文件或目錄屬性,複製到 buf 中;成功返回 0,失敗返回 -1 58 int lstat( const char *path, struct stat *buf ); 和 stat 區別在於若是文件是軟連接,會獲取軟連接自己的屬性 59 int fstat( const int filedes, struct stat *buf); 和 stat 區別在於他使用文件描述符 60 61 int S_ISREG( buf.st_mode ); 普通文件 62 int S_ISDIR( buf.st_mode ); 目錄 63 int S_ISCHR( buf.st_mode ); 字符設備文件 64 int S_ISBLK( buf.st_mode ); 塊設備 65 int S_ISFIFO( buf.st_mode ); 有名管道 66 int S_ISLNK( buf.st_mode ); 軟連接 67 int S_ISSOCK( buf.st_mode ); 套結字文件 68 69 int S_ISUID( buf.st_mode ); 執行時設置用戶 ID 70 int S_ISGID( buf.st_mode ); 執行時設置組 ID 71 int S_ISVTX( buf.st_mode ); 保存正文 72 int S_IRWXU( buf.st_mode ); 用戶(全部者)讀、寫、執行 73 int S_IRUSR( buf.st_mode ); 用戶讀 74 int S_IWUSR( buf.st_mode ); 用戶寫 75 int S_IXUSR( buf.st_mode ); 用戶執行 76 int S_IRWXG( buf.st_mode ); 組讀、寫、執行 77 int S_IRGRP( buf.st_mode ); 組讀 78 int S_IWGRP( buf.st_mode ); 組寫 79 int S_IXGRP( buf.st_mode ); 組執行 80 int S_IRWXO( buf.st_mode ); 其餘讀、寫、執行 81 int S_IROTH( buf.st_mode ); 其餘讀 82 int S_IWOTH( buf.st_mode ); 其餘寫 83 int S_IXOTH( buf.st_mode ); 其餘執行 84 85 int MAJOR( buf->st_rdev ); 獲取主設備號 86 int MINOR( buf->st_rdev ); 獲取次設備號 87 88 time_t time( time_t *tp ); 返回系統時間給 tp ,返回自 epoch 到如今的秒數;成功返回值也是 tp,失敗返回 -1 89 int gettimeofday( struct timeval *tv, struct timezone *tz ); 獲得當前時間和時區,在 sys/time.h 中,分別寫到 tv 和 tz 中, tz 常爲空,若是 tz 爲 NULL 則不向 tz 寫入;成功返回 0,失敗返回 -1;使用時不要使用結構體指針 90 char *ctime( time_t *tp ); 將日曆時間轉換爲字符串返回,必須包含 time.h 頭文件,否則會出現段錯誤 91 struct tm *gmtime( time_t ); 92 sturct tm *localtime( time_t ); 將日曆時間轉換爲結構體記錄的時間 93 char *asctime( const struct *tm ); 將結構體時間轉換爲字符串返回 94 size_t strftime( char *s, size_t max, const char *format, const struct tm *tm ); 將結構體記錄時間轉換爲自定義格式的字符串 95 time_t mktime( struct tm *tm ); 將結構體記錄的時間轉換爲日曆時間 96 clock_t clock(void); 成功返回程序開始到調用此函數時使用 CPU 的時間,不考慮子進程等,標準 POSIX 精確到10ms 97 98 DIR *opendir( const char *name ); 成功返回 DIR* 形態的目錄流,失敗返回 NULL 99 struct dirent *readdir( DIR *dir ); 每次讀取一條目錄結構;成功返回 dirent 指針,失敗返回 NULL 100 int closedir( DIR *dir ); 失敗返回 -1;錯誤緣由存在 errno 中 101 void rewinddir( DIR *dirp ); 迴繞目錄,回到目錄流開始處,不用關閉目錄 102 103 ssize_t readlink( const char *path, char *buf, size_t bufsize ); 返回軟連接指向文件的文件名存放在 buf 中,不包括字符串結束符'\0',須要本身添加; buf 是字符數組; bufsize 是 buf 大小;成功返回是軟連接指向文件文件名的長度,失敗返回 -1 104 105 struct passwd *getpwuid( uid_t uid ); 在 pwd.h 中,得到 uid 對應用戶的屬性信息,失敗返回 NULL 106 struct group *getgrgid( gid_t gid ); 在 grp.h 中,失敗返回 NULL 107 108 109 多進程編程 110 111 pid_t getpid( void ); 得到調用進程的 id 112 pid_t getppid( void ); 113 char *getenv( const char *name ); 獲取環境變量 114 int putenv( const char *str ); 新建環境變量( str like " name = string " ) 115 int setenv( const char *name, const char *value, int rewrite ); 設置環境變量,若已存在,則參考 rewrite 參數 116 int fork(); 成功子進程返回值爲 0 ,父進程返回子進程 pid,失敗返回 -1 給父進程 117 int dup( fildes ); 複製已存在的文件描述符 fildes(默認爲 0 ), 成功返回新的文件描述符 118 int dup2( int fildes, int fildes2 ); 進程內部複製文件描述符,若是 fildes2 已是一個文件描述符,則先關閉,成功則返回 fildes2 119 pid_t wait( int *status ); 父子進程同步(阻塞父進程),等待任何子進程,子進程變成殭屍進程也能夠銷調; status 用於存放子進程結束狀態;成功則返回子進程 id 號,失敗返回 -1 120 pid_t waitpid( pid_t pid, int *status, int options ); 等待子進程結束; pid == -1 等待任何子進程, > 0 等待進程 id 和 pid 相等的子進程, == 0 等待其組 id 等於調用進程的組 id 的任一子進程, < -1 等待其組 id 等於 pid 的絕對值的任一子進程; options 設置等待方式, 0 不設置, WNOHANG 若是沒有任何已結束的進程則當即返回, WUNTRACED 若是子進程進入暫停狀態則當即返回 121 122 int execl( const char *pathname, const char *arg0, ..., (char *)0 ); 成功不返回任何值,失敗返回-1;pathname 是執行文件的全路徑名,arg0 是文件執行的第一個參數,以 ( char * )0 表示命令行參數的結束 123 int execv( const char *pathname, char *const argv[] ); 124 int execle( const char *pathname, const char *arg0, (char *)0, char *const envp[] ); envp 是新程序的環境變量 125 int execve( const char *pathname, char *const argv[], char *const envp[] ); 系統調用,其餘 5 個是封裝的 execve 126 int execlp( const char *filename, const char *arg0, ..., (char *)0 ); 127 int execvp( const char *filename, char *const argv[] ); 128 E 傳遞環境變量表,L 單獨的參數傳遞(最後須要一個 NULL),V 傳一個指針數組做爲命令行參數,P 按照 PATH 查找新程序 129 130 void fflush( stdout ); 刷新輸出緩衝區(強制 printf 提交內容) 131 void fgets( buf, 100, stdin ); 輸入字符串 132 133 void exit( int status ); stdlib.h, 返回內核前作些清理工做,包括調用 Exit handler, 完全關閉 I/O 流(將緩衝區數據都提交給內核 134 void _exit( int status ); unistd.h, 當即返回內核,不執行 exit handler, 不刷新 I/O 流 135 int atexit( void ( *func )( void )); 註冊 exit handler,函數無參數,無返回值,在 ANSI C 中,最多註冊 32 個 exit handler,按註冊順序逆序調用;成功返回 0 136 int on_exit( void ( *func )( int, void * ),void *arg ); 註冊 exit handler, 函數有兩個參數,一個 int 參數(是系統回調函數時傳給函數進程的退出值),另外一個參數是指針 arg(任何指針均可作參數),參數的值爲程序執行完後的值,這時緩衝區內容被刪除了,堆棧區內容沒有被刪除 137 138 void getpgrp() 返回調用進程的進程組 id (進程組組長的 id ) 139 void setpgid() 參加一個現有進程組或建立一個新進程組,建立守護進程 daemon ,建立時最好關閉全部文件描述符等 140 int setsid(); 若是調用此函數的進程不是一個進程組組長就建立一個新對話期( session )(多個進程組集合),此進程變爲新對話期的首進程,成爲新進程組的組長,此進程沒有控制終端;是進程組組長則返回出錯 141 void chdir("/tmp"); 改變工做目錄 142 void umask(0); 將 umask 改成 0 143 pid_t sysconf( _SC_OPEN_MAX ); 返回系統容許打開的文件描述符最大數目 144 pause(); 暫停程序 145 146 void openlog( const char *indent, int option, int facility ); 使用 syslog 能夠沒有這個函數; indent 指向的字符串將出如今每條消息的最前面; option 爲 LOG_CONS 表示當向 syslog 守護進程傳送消息失敗時把消息寫入系統控制檯, LOG_PID 表示守護進程的 pid 將出如今每條消息中, LOG_NDELAY LOG_NOWAIT LOG_ODELAY LOG_PERROR; facility 爲 LOG_DAEMON 表示消息由系統守護進程發送, LOG_AUTH LOG_AUTHPRIV LOG_CRON LOG_FTP LOG_KERN LOG_NEWS LOG_SYSLOG LOG_USER LOG_UUCP LOG_LOCAL0~LOG_LOCAL7 OG_LPR OG_MAIL 147 void syslog( int priority, const char *format,... ); 向 syslogd 守護進程送出消息(寫入 /var/log/messages 中); priority 表示消息緊急程度,能夠是 LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE LOG_INFO LOG_DEBUG; format 是寫入消息的字符串,能夠和 printf 同樣使用格式化串 148 void closelog( void ); 使用 syslog 能夠沒有這個函數; 149 150 151 進程間通訊 152 153 void ( *signal( int signum, void (*handler)(int)) )(int); 可靠性低,在一個信號處理程序運行時接收到其餘信號可能打斷當前處理程序運行,可用 sigaction() 代替;成功返回可用信號處理函數( void (*)(int) ),失敗返回 SIG_ERR; handler 時信號處理函數的函數指針,有個 int 參數(爲系統傳給處理函數的信號值),還能夠是 SIG_IGN(忽略該信號)、 SIG_DFL(採用默認行爲) 154 int kill( pid_t pid, int sig ); 發送信號到進程,成功返回 0,失敗返回 -1 155 int alarm( unsigned int seconds ); 在 seconds 秒後發送 SIGALRM 信號,seconds 爲 0 則取消設置的鬧鐘;成功則返回上一個鬧鐘還剩多少時間,失敗返回 -1 156 void abort(void); 結束進程,並向父進程發送 SIGABRT 信號 157 158 int WIFEXINTED( int status ); 判斷子進程的返回狀態是否是正常,正常退出返回真 159 int WEXITSTATUS( int status ); 返回子進程正常退出的狀態值 160 int WIFSIGNALED( int status ); 判斷子進程退出狀態是不是非正常退出,非正常退出返回真 161 int WTERMSIG( int status ); 返回非正常退出狀態的信號 162 163 int sigemptyset( sigset_t *set ); 清空信號集合,全 0 ,不阻塞任何信號 164 int sigfillset( sigset_t *set ); 將信號集合置位,阻塞相應的信號 165 int sigaddset( sigset_t *set, int signum ); 對應位置 1 166 int sigdelset( sigset_t *set, int signum ); 對應位置 0 167 int sigpending( sigset_t *set ); 將正在被阻塞的信號記錄到集合中,獲取阻塞了的信號集合 168 int sigismember( const sigset_t *set, int signum ); 集合中對應信號位爲 1 則返回真,用來判斷集合中是否由此信號 169 int sigprocmask( int how, const sigset_t *set, sigset_t *oldset ); 用來得到和改變調用進程的信號掩碼,當前信號集合會賦值給 oldset;使用時在關鍵代碼前設置掩碼,而後執行關鍵代碼,以後獲取被阻塞的信號,逐步處理信號; how = SIG_BLOCK 信號集合掩碼設置爲當前信號集合與 set 的並集, how = SIG_UNBLOCK 設置爲當前信號集合減去 set 中的信號, how =SIG_SETMASK 設置爲 set 170 171 int sigaction( int signum, const struct sigaction *act, struct sigaction *oldact ); signum 不能是 SIGSTOP 或者 SIG_KILL, oldact 返回之前的 act,能夠指定爲 NULL 172 173 int pipe( int fd[2] ); 無名管道,寫入 fd[1], 從 fd[0] 讀取,只能在有親緣關係的進程間通訊;成功返回 0,失敗返回 -1 174 175 int mkfifo( char *pathname, mode_t mode ); 有名管道,打開管道文件進行讀寫,若是管道爲空,進程將阻塞,管道關閉寫端再讀時將當即返回,返回值爲 0,讀端關閉寫端再寫將產生 sigpipe 信號,默認結束進程 176 177 int shmget( key_t key, size_t size, int shmflg ); key 值惟一標誌共享內存( Shared memory );size 是創建內存大小;shmflg = IPC_CREAT 若是共享內存不存在則建立一個,存在則得到該內存;shmflg = IPC_EXCL 只有共享內存不存在時才建立,否則就產生錯誤;成功則返回共享內存標誌碼,其惟一標誌一塊共享內存,錯誤返回 -1 178 void *shmat( int shmid, const void *shmaddr, int shmflg ); 容許進程訪問一塊共享內存;shmid 是 shmget 的返回值;shmaddr 是共享內存在本進程中的虛擬地址起始地址,一般程序員不知道就填 0;shmflg 是進程對該共享內存的操做模式,SHM_RDONLY 表示只讀模式,0 表示可讀可寫;成功返回共享內存的虛擬地址起始地址(數組名),失敗返回 -1 179 int shmdt( const void *shmaddr ); 斷開共享內存區的映射,成功返回 0,失敗返回 -1 180 int shmctl( int shmid, int cmd, struct shmid_ds *buf ); cmd = IPC_RMID 刪除共享內存;buf 是保存內存模式狀態和訪問權限的數據結構,常爲 NULL;成功返回 0,失敗返回 -1 181 182 int semget( key_t key, int nsems, int semflg ); 獲取信號量數組; key 惟一標誌信號量( Semaphore );nsems 是信號量個數,通常爲 1(若干個信號量組合在一塊兒造成信號量數組,其實 nsems 就是指定數組元素個數); semflg 標誌至關於信號量的訪問權限;成功返回信號量標誌碼,失敗返回 -1 183 int semctl( int semid, int semnum, int cmd , ...); 控制信號量,設初值或是刪除信號量集、查看信號量信息等; semnum 信號量編號,用於指定要操做的信號量是信號量數組中的哪個; cmd 爲 IPC_STAT 讀取一個信號量集的數據結構 semid_ds ,並將其存放在 union semun 類型的第四個參數的 buf 中; IPC_SET 設置信號量集的數據結構 semid_ds 中的元素 ipc_perm,其值取自 union 類型的第 4 個參數 buf; IPC_RMID 將信號量集從內存中刪除; GETALL 讀取信號量集中的全部信號量值; GETNCNT 返回正在等待資源的進程數目; GETPID 返回最後一個執行 semop 操做的進程 pid; GETVAL 返回信號量集中單個的信號量的值; GETZCNT 返回正在等待玩空空閒的資源的進程數目; SETALL 設置信號量集中的全部信號量的值; SETVAL 設置信號量集中的一個單獨信號量的值,被設置的值在 union semun 類型的第 4 個參數的 val 中;最後的省略號表示可能有第 4 個參數,若是 cmd 要設置初值就是第 4 個參數 184 int semop(int semid, struct sembuf *sops, size_t nsops ); semid 指明操做的信號量數組; sops 包含了具體的操做(P/V),詳見結構體部分;nsops 說明 sops 指向的結構體數量,一般爲 1 185 186 int msgget( key_t key, int flag ); 打開現存隊列或建立消息隊列,成功返回消息隊列 msgid ,失敗返回 -1 187 int msgsnd( int msgid, const void *ptr, size_t nbytes, int flag ) ptr 指向一個長整形數,包含了正長整形的消息類型,在其後當即跟隨了消息數據,nbytes 是消息長度(爲 0 則無數據),若發送的最長消息是 512,則定義結構體:struct mymesg{ long mtype;/*positive message type*/ char mtext[512];};, ptr 即指向這個結構體,接受這可使用消息類型以非先進先出的次序; flag 爲 IPC_NOWAIT 時,當消息隊列滿會使得 msgsnd 當即出錯返回,errno 被置爲 EAGAIN ,若不設爲 IPC_NOWAIT,進程會一直阻塞直到有空閒空間或系統刪除了此隊列( errno 被置爲 EIDRM )或捕捉到信號從信號處理程序返回( errno 被置爲 EINTR );成功返回 0,失敗返回 -1 188 int msgrcv( int msgid, void *ptr, size_t nbytes, long type, int flag ); ptr 和 msgsnd 同樣;nbytes 說明緩衝區長度,若返回消息大於 nbytes,若是在 flag 中設置了 MSG_NOERROR, 則截短消息(這種狀況下出錯回返回信息),若是沒有設置此標誌,則出錯返回 E2BIG (消息仍留在隊列中); type == 0 返回隊列中的第一個消息, type > 0 返回隊列中消息類型爲 type 的第一個消息, type < 0 返回隊列中消息類型小於或等於 type 絕對值,且其類型值又最小的消息(設置優先級); flag 值爲 IPC_NOWAIT 使操做不阻塞,這是若是沒有指定消息,則出錯返回 ENOMSG,不爲 IPC_NOWAIT 時處理方式和 msgsnd 同樣;成功返回數據長度,失敗返回 -1 189 190 191 多線程編程初步 192 193 int pthread_create( pthread_t *thread, pthread_attr_t *attr, void *(*func)(void*), void *arg); thread 是被建立線程的標識; attr 是線程的屬性的指針,NULL 爲使用默認屬性; func 被建立線程的程序代碼( (void*) funcname ),無返回值; arg 是 func 的參數,是一個指針,可爲 NULL。 194 pthread_exit( void *reval ); 線程自行結束,retval 存放線程退出狀態 195 int pthread_join( pthread_t th, void **thread_return ); 等待 th 線程結束,指針 thread_return 指向的位置存放的是終止線程的返回狀態, void 類型,可強制轉換爲 int 型,調用時使用 &thread_return,可設爲 NULL;成功返回 0,失敗 EINVAL、 ESRCH 或其餘(失敗緣由多是這個線程是分離的) 196 197 pthread_mutex_t mutex; 198 pthread_mutex_init( &mutex, NULL ); 在主線程中初始化鎖爲解鎖狀態 199 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 在編譯時初始化爲解鎖狀態,不用上面的步驟咯 200 pthread_mutex_lock( &mutex ); 在訪問對象前加鎖( P 操做 ),若是已被加鎖,則阻塞直到鎖打開 201 pthread_mutex_unlock( &mutex ); 訪問對象後解鎖( V 操做 ) 202 pthread_mutex_trylock( &mutex ); 加鎖對象已被加鎖,當即返回,返回值爲 EBUSY 203 204 int sem_init( sem_t *sem, int pshared, unsigned int value ); 初始化信號量,sem 爲指向信號量結構的一個指針; pshared 不爲 0 時此信號在進程間共享,不然只能在當前進程的全部線程共享; value 給出信號量初值;成功返回 0,失敗返回 -1 205 int sem_wait( sem_t *sem ); 信號量減 1;當 sem 爲 0 時阻塞;成功返回 0,失敗返回 -1 206 int sem_post( sem_t *sem ); 信號量加 1;當有線程阻塞時調用這個函數使得其中一個進程再也不阻塞,選擇機制由線程調度策略決定;成功返回 0 ;失敗返回 -1 207 int sem_destroy( sem_t *sem ); 刪除信號量,成功返回 0,失敗返回 -1 208 209 int pthread_attr_init( pthread_attr *attr ); 初始化線程屬性結構,設置好 attr 後才能建立線程,主要包括是否綁定,是否分離,堆棧地址,堆棧大小,優先級,默認非綁定、非分離、1 MB 的堆棧,與進程相同優先級;綁定是將線程「綁」在一個輕進程上,被綁定的進程具備較高的響應速度;分離狀態決定了線程以什麼方式終結本身,非分離線程只有等待建立的線程結束才能釋放本身佔用的資源( pthread_join 返回時建立的線程擦才結束),而分離線程不會被其餘線程所等待,運行結束就釋放資源 210 int pthread_attr_destroy( pthread_attr_t *attr ); 211 int pthread_attr_setscope( pthread_attr *attr, PTHREAD_SCOPE_SYSTEM ); 設置綁定狀態,PTHREAD_SCOPE_SYSTEM 爲綁定,PTHREAD_SCOPE_PROCESS 爲非綁定 212 int pthread_attr_setdetachstate( pthread_attr_t *attr, int detachstate ); 第二個參數選擇 PTHREAD_CREATE_DETACHED 爲分離, PTHREAD_CREATE_JOINABLE 爲不分離 213 int pthread_cond_timewait(); 留出足夠時間讓函數 pthread_create 執行完,避免錯誤;設置一個分離線程,若是他運行很快,他可能在函數 pthread_create 返回以前就終止,這樣函數就可能返回錯誤的線程號 214 int pthread_attr_getschedparam( pthread_attr_t *attr, struct sched_param *param ); 獲得線程優先級,存放在結構體 sched_param 中,param.sched_priority = 10 215 int pthread_attr_setschedparam( pthread_attr_t *attr, const struct sched_param *param ); 設置線程優先級 216 217 int pthread_cancel( pthread_t tid ); 一個線程殺死另外一個線程時調用, tid 是線程標識 218 int pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL ); 設置線程屬性拒絕被殺死, PTHREAD_CANCEL_ENABLE 表示容許被殺死(缺省) 219 int pthread_setcanceltype( PTHREAD_CANCEL_DEFDERRED, NULL ); 設置延後被殺死(缺省),PTHREAD_CANCEL_ASYNCHRONOUS 當即被殺死 220 void pthread_testcancel( void ); 用於設置殺死點,在延遲殺死的狀況下,線程會在收到殺死請求後延遲至第一個殺死點時被殺死;殺死點是在被殺死的進程中,殺死點有調用 testcancel 的點和引發進程阻塞的系統調用( sleep )處, 221 int pthread_detach( pthread_t tid ); 設置線程不須要被 pthread_join, 由於已經結束的線程沒有被 pthread_join 將會在系統中累積殭屍進程 222 223 224 網絡編程 225 226 int socket( int family, int type, int protocol ); 返回套結字的文件描述符; family 是協議或地址族,TCP/IP 爲 PF_INET 或 AF_INET; type 是服務類型,TCP 是 SOCK_STREAM, UDP 是 SOCK_DGRAM; protocol 是使用的協議號,用 0 指定 family 和 type 的默認協議號;成功則返回 sockfd,失敗返回 -1 227 int bing( int sockfd, const struct sockaddr *localaddr, socklen_t addrlen ); 爲一個套結字指明一個本地 IP 和協議端口號;sockfd 是 socket 建立的套結字描述符; localaddr 是一個地址結構,指定 IP 地址和協議端口號; addrlen 是地址結構的字節數大小;成功返回 0,失敗返回 -1 228 int listen( int sockfd, int queuelen ); 使套結字處於監聽狀態; queuelen 是請求隊列大小,並非一個準確的鏈接數;成功返回 0 ,失敗返回 -1 229 int accept( int sockfd, struct sockaddr *addr, socklen_t *addrlen ); 只用於流套結字,從監聽隊列中取走下一個鏈接請求,建立一個新套結字,並返回新套結字描述符; addr 是一個地址結構的指針,調用 accept 成功後在該結構中填入遠程機器的 IP 地址和協議端口號; addrlen 初始指定爲 struct sockaddr 結構體大小的存放地址,調用 accept 後在其中填入遠程機器 socket 地址的實際大小;成功返回一個非負套結字描述符,失敗返回 -1 230 int connet(int sockfd, const struct sockaddr * addr, socklen_t addrlen ); 容許調用者爲先前建立的套結字指明遠程端點的地址,若是套結字使用了 TCP ,他就使用 3 次握手創建一個鏈接;成功返回 0 231 232 ssize_t sendto( int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen ); 向指定數據接收端發送指定數據;dest_addr 爲 NULL ,addrlen 爲 0 時等於 send; flags 發送標識,通常爲 0; dest_addr 數據接收端地址結構體的指針;addrlen 數據接收端地址結構體大小;成功返回實際發送的數據,失敗返回 -1 233 ssize_t recvfrom( int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen ); src_addr 存放數據發送端的地址; addrlen 是 src_addr 的大小,不須要 src_addr 和 addrlen 置爲 NULL;成功返回實際接收到的字節數,失敗返回 -1 234 235 ssize_t send( int sockfd, const void *buf, size_t len, int flags ); 返回時發送出去的字節(同步)或發送到 socket 緩衝區的字節(異步),系統默認發送和接受一次爲 8688 B( 8.5 K ) 236 ssize_t recv(int sockfd, void *buf, size_t len, int flags); flags 爲 0 時等於 write/read, flags 參數爲 MSG_DONTROUTE send 不查找路由表(目標在本地網絡),MSG_OOB send/recieve 帶外數據, MSG_PEEK recieve 查看數據並不從系統緩衝區移走數據, MSG_WAITALL recieve 阻塞,等待全部數據,返回值等於 len 237 ssize_t sendmsg( int sockfd, const struct msghdr *msg, int flags ); 238 ssize_t recvmsg( int sockfd, const struct msghdr *msg, int flags ); 239 240 int shutdown( int fd, int how ); TCP 鏈接是雙向的,使用 close 會把讀寫通道都關閉, shutdown 只關閉一個方向; how 爲 SHUT_WR 再也不發送, SHUT_RD 再也不讀,接收到的對端數據都將被確認,而後丟棄, SHUT_RDWR 與 close 不一樣, colse 把描述字的引用計數減 1,當計數變爲 0 時才關閉該套結字,而 shutdown 直接就發送 FIN 分節(父進程的關閉操做將致使客戶端的網絡鏈接被關閉) 241 242 uint16_t htons( uint16_t hostshort ); 將 unsigned short 類型的數據的主機字節順序轉換爲網絡字節順序 243 unsigned long int htonl( unsigned long int hostlong ); 將本機上的 long 轉換爲網絡上的 long 244 unsigned short int htons( unsigned short int hostshort ); 245 unsigned long int ntohl( unsigned long int netlong ); 246 unsigned short int ntohs( unsigned short int netshort ); 247 248 int inet_pton( int af, const char *src, void *dst ); 將點分格式的地址字符串轉換爲網絡字節序整型數;af 爲 AF_INET 或 AF_INET6;src 點分格式的地址; dst 轉換後的地址;成功返回 1,錯誤返回 -1 249 const char *inet_ntop( int af, const void *src, char *dst, socklen_t cnt ); 將網絡字節序整型轉換爲點分格式的 ip 地址; src 整形變量地址; des 用來存儲轉換後的數據的地址; cnt 存儲空間大小 常爲 16;成功後返回轉換後的地址,失敗返回 NULL 250 251 int inet_aton(const char *cp, struct in_addr *inp); 將點分十進制 IP 地址 cp 轉換爲二進制數 inp;成功返回非 0,失敗返回 0 252 in_addr_t inet_addr(const char *cp); 將點分十進制 IP 地址 cp 轉換爲二進制數;成功返回二進制地址,失敗返回 -1 253 char *inet_ntoa(struct in_addr in); 將二進制地址轉換爲點分十進制 254 255 struct hostent *gethostbyname( const char *hostname ); 將機器名(如 linux.yu.net )轉換爲一個結構體指針,指針裏存放了域名和 IP 地址等信息 256 struct hostent *gethostbyaddr( const void *addr, int len, int type ); 將一個 socket 地址結構體裏面的 IP 地址轉換爲一個結構體指針;失敗返回 NULL 且設置 h_errno 錯誤變量 257 char *h_strerror(int errnum); 打印詳細的錯誤信息( h_errno ) 258 259 int getsockname( int sockfd, struct sockaddr *localaddr, int *addrlen ); 獲取套結口 sockfd (已綁定的)的本端 socket 地址,存放到 localaddr 中,其長度放到 addrlen 中;成功返回 0,失敗返回 -1 260 int getpeername( int sockfd, struct sockaddr *peeraddr, int *addrlen ); 獲取套結口 sockfd 的遠端 socket 地址 261 struct servent *getservbyname( const char *servname, const char *protoname ); 經過服務獲得端口號 262 struct servent *getservbyport( int port, const char *protoname ); 獲得指定端口號的服務(知名服務和端口號對應) 263 264 int getsockopt( int sockfd, int level, int optname, void *optval, socklen_t *optlen ); 得到 socket 屬性 265 int setsockopt( int sockfd, int level, int optname, const void *optval, socklen_t optlen ); 設置 socket 屬性 266 int setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); 在 socket 和 bind 之間設置容許地址重用套結字選項(解決不能綁定到指定地址);設置套結口屬性 SO_REUSEADDR,在一臺機器上運行多個服務通配地址被佔用時要設置這個屬性;on 爲整數 1,表示 true; 267 int setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( const char* )&bReuseaddr, sizeof(bReuseaddr) ); 關閉 socket 後想繼續重用該 socket;bReuseaddr = 1 268 int setsockopt( s, SOL_SOCKET, SO_DONTLINGER, ( const char* )&bDontLinger, sizeof(bDontLinger) ); 處於鏈接狀態的 socket 在調用 close 後當即關閉,不經歷 TIME_WAIT 269 int setsockopt( socket, SOL_SOCKET, SO_SNDTIMEO, ( char * )&nNetTimeout, sizeof(int) ); 設置發送時限爲 nNetTimeout ,單位是毫秒 270 int setsockopt( socket, SOL_SOCKET, SO_RCVTIMEO, ( char * )&nNetTimeout, sizeof(int) ); 設置接收時限爲 nNetTimeout 271 int setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( const char* )&nRecvBuf, sizeof(int) ); 設置接收緩衝大小 32 * 1024 B,避免 send() recv() 不斷循環收發 272 int setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( const char* )&nSendBuf, sizeof(int) ); 設置發送緩衝區大小 273 int setsockopt( s, SOL_SOCKET, SO_SNDBUF, ( char* )&nZero, sizeof(int) ); nZero = 0, 在發送數據時不經歷由系統緩衝區複製到 socket 緩衝區而影響程序性能 274 int setsockopt( s, SOL_SOCKET, SO_RCVBUF, ( char* )&nZero, sizeof(int) ); nZero = 0, 在接收數據時不經歷由 socket 緩衝區複製到系統緩衝區而影響程序性能 275 int setsockopt( s, SOL_SOCKET, SO_BROADCAST, ( const char* )&bBroadcast, sizeof(int) ); bBroadcast = 1, 發送的數據具備廣播特性 276 int setsockopt( s, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, ( const char* )&bConditionalAccept, sizeof(int) ); bConditionalAccept = 1, client 鏈接服務器過程當中,在非阻塞模式(阻塞模式下沒用)下 connect 過程當中設置 connect 延時到 accept 被呼叫 277 int setsockopt( s, SOL_SOCKET, SO_LINGER, ( const char* )&m_sLinger, sizeof(linger) ); 在關閉 socket 時容許數據發送完再關閉 socket;使用結構體 linger( 實例 m_sLinger ),設置 m_sLinger.l_onoff = 1;在 close 過程當中數據還沒發送完畢時容許逗留 m_sLinger.l_linger = 5;容許逗留 5 s; 278 279 280 281 頭文件 282 283 284 stdlib.h atexit, on_exit, pipe, malloc, abort 285 stdio.h printf, perror 286 unistd.h STDIN_FIFLNO(0), STDOUT_FIFLNO, STDERR_FIFLNO, dup2, _exit, alarm 287 fcntl.h O_CREAT, O_APPEND, O_EXCL, O_RDONLY 288 poll.h 289 curses.h 編譯時要指定庫 ncurses,缺乏時安裝 kernel-devel ncurses-devel 290 errno.h EXIT_SUCCESS, EXIT_FAILED, perror 291 limits.h PIPE_BUF( 4096 ), 292 netdb.h 網絡, struct hostent, 293 time.h 294 dirent.h 目錄 295 pwd.h 296 grp.h 297 pthread.h 線程 298 semaphore.h 信號量 299 signal.h 300 string.h 301 strings.h strcasecmp, bzero 302 syslog.h 303 304 arpa/inet.h 網絡 305 306 sys/ioctl.h 307 sys/ipc.h 308 sys/msg.h 消息隊列 309 sys/select.h 310 sys/sem.h 信號量 311 sys/shm.h 共享內存 312 sys/socket.h 313 sys/stat.h 314 sys/time.h gettimeofday 315 sys/types.h 316 sys/wait.h 317 318 319 320 自定義類型 321 322 323 FILE 324 DIR 325 atomic_t typedef struct { volatile int counter; } atomic_t; 326 bool typedef _Bool bool; 327 clockid_t typedef __kernel_clockid_t clockid_t; 328 daddr_t typedef __kernel_daddr_t daddr_t; 329 dev_t typedef __kernel_dev_t dev_t; 330 gid16_t typedef __kernel_gid16_t gid16_t; 331 gid_t typedef __kernel_gid32_t gid_t; 332 id_t 能夠涵蓋任務 pid_t,uid_t 或者 gid_t 的整數類型,不能分割來使用 333 ino_t typedef __kernel_ino_t ino_t; 334 in_addr_t 335 in_port_t typedef uint16_t in_port_t; 336 key_t typedef __kernel_key_t key_t; 337 loff_t typedef long long __kernel_loff_t; typedef __kernel_loff_t loff_t; 338 mode_t typedef unsigned int __kernel_mode_t; typedef __kernel_mode_t mode_t; 339 mqd_t typedef __kernel_mqd_t mqd_t; 340 nlink_t typedef __kernel_nlink_t nlink_t; 341 off_t typedef __kernel_off_t off_t; 342 old_gid_t typedef __kernel_old_gid_t old_gid_t; 343 old_uid_t typedef __kernel_old_uid_t old_uid_t; 344 pid_t typedef __kernel_pid_t pid_t; 345 sa_family_t typedef unsigned short int sa_family_t; 346 sem_t typedef long sem_t; 347 size_t typedef __kernel_size_t size_t; 348 ssize_t typedef __kernel_ssize_t ssize_t; 349 suseconds_t typedef long __kernel_suseconds_t; typedef __kernel_suseconds_t suseconds_t 350 timer_t typedef __kernel_timer_t timer_t; 351 time_t typedef long time_t; 352 uid16_t typedef __kernel_uid16_t uid16_t; 353 uid_t typedef __kernel_uid32_t uid_t; 354 uintptr_t typedef unsigned long uintptr_t; 355 __kernel_clock_t typedef long __kernel_clock_t; 356 __kernel_gid_t typedef unsigned short __kernel_gid_t; 357 __kernel_ino_t typedef unsigned long __kernel_ino_t; 358 __kernel_ipc_pid_t typedef unsigned short __kernel_ipc_pid_t; 359 __kernel_mode_t typedef unsigned short __kernel_mode_t; 360 __kernel_nlink_t typedef unsigned short __kernel_nlink_t; 361 __kernel_off_t typedef long __kernel_off_t; 362 __kernel_pid_t typedef int __kernel_pid_t; 363 __kernel_ptrdiff_t typedef int __kernel_ptrdiff_t; 364 __kernel_size_t typedef unsigned int __kernel_size_t; 365 __kernel_ssize_t typedef int __kernel_ssize_t; 366 __kernel_suseconds_t typedef long __kernel_suseconds_t; 367 __kernel_timer_t typedef int __kernel_timer_t; 368 __kernel_time_t typedef long __kernel_time_t; 369 __kernel_uid_t typedef unsigned short __kernel_uid_t; 370 371 POSIX-Portable Operating System Interface for Unix,要求C語言庫的 <.../types.h> 頭文件爲每一個實現 POSIX 的機器定義一個一致的類型集。其中的每個類型定義很容易與本地C語言區分開來,由於它們都以_t結尾。 372 373 374 375 結構體 376 377 struct timeval //使用範圍: gettimeofday,設置時間間隔,沒有定義在 time.h 中 378 { 379 time_t tv_sec; //用 gettimeofday 建立結構體時獲得到 Epoch 時的秒數 380 suseconds_t tv_usec; //微秒數,六位;在實際中,該函數以及 Linux 內核返回的 timeval 類型的時間值, tv_usec 表明的是微秒精度(10的-6次方秒) 381 }; 382 383 struct timezone { 384 int tz_minuteswest; /* minutes west of Greenwich */ 385 int tz_dsttime; /* type of DST correction */ 386 }; 387 388 struct pollfd{ 389 int fd; //文件描述符 390 short events; // requested events 用於輸入 391 short revents; // returned events 用於輸出,能夠是 events 中指定已發生的事件,也能夠是 POLLERR POLLHUP POLLNVAL 3 個錯誤中的一個 392 } 393 394 struct stat{ 395 dev_t st_dev; //id of device containing file 396 ino_t st_ino; //inode number 397 mode_t st_mode; //protection 398 nlink_t st_nlink; //hard link number 399 uid_t st_uid; 400 gid_t st_gid; 401 dev_t st_rdev; //device id( if special device ) 主次設備號 402 off_t st_size; //total size, in bytes 403 blksize_t st_blksize; //blocksize for filesystem I/O 404 blkcnt_t st_blocks; //number of blocks allocated 405 time_t st_atime; //access 406 time_t st_mtime; //modification 407 time_t st_ctime; //status change 408 } 409 410 struct tm{ 411 int tm_sec; 412 int tm_min; 413 int tm_hour; 414 int tm_mday; 415 int tm_mon; 416 int tm_year; 417 int tm_wday; 418 int tm_yday; 419 int tm_isdst; 420 } 421 422 struct dirent{ 423 ino_t d_ino; //inode number 424 off_t d_off; //offset to the next dirent 425 unsigned short d_reclen; //length of this record 426 unsigned char d_type; //type of file 427 char d_name[256]; //filename 428 } 429 430 struct passwd{ 431 char *pw_name; //用戶名 432 char *pw_passwd; //用戶密碼 433 uid_t pw_uid; 434 gid_t pw_gid; 435 char *pw_gecos; //用戶真實姓名 436 char *pw_dir; //用戶主目錄 437 char *pw_shell; //用戶主 shell 程序 438 } 439 440 struct sigaction{ 441 void ( *sa_handler )( int ); //信號處理程序,有一個 int 參數 442 void ( *sa_sigaction )( int, siginfo_t *, void * ); //信號處理程序,第一個參數是信號,第二個參數是指向 siginfo_t 的指針,第三個參數是指向 ucontext_t 的指針 443 sigset_t sa_mask; //信號掩碼集合,該集合中屏蔽的信號將在信號處理程序結束以後再被處理,默認屏蔽同類信號 444 int sa_flags; //信號處理程序行爲標誌,SA_SIGINFO 表示使用 sa_sigaction 代替 sa_handler; SA_NODEFER 表示不屏蔽同類信號,SA_NOCLDSTOP 若 signum 是 SIGCHLD,當一個子進程中止時,不產生此信號; SA_RESTART 由此信號中斷的系統調用自動重啓; SA_ONSTACK 若用 sigaltstack 已說明了一替換棧,則此信號遞送給替換棧上的進程; SA_NOCLDWAIT 若 signum 是 SIGCHLD,則當調用進程的子進程終止時,不建立殭屍進程,若調用進程在後面調用 wait,則阻塞到它全部子進程都終止,此時返回 -1; SA_RESETHAND 對此信號的處理方式在此信號捕捉函數的入口處復原爲 SIG_DFL 445 void ( *sa_restorer )( void ); //再也不使用 446 }; 447 448 union semun{ 449 int val; //SETVAL 450 struct semid_ds *buf; //IPC_STAT IPC_SET 451 unsigned short *array; //GETALL SETALL 452 struct seminfo *__buf; //IPC_INFO 453 }; 454 455 struct sembuf{ 456 unsigned short sem_num; // 操做信號在信號量集中的編號,第一個編號爲 0 457 short sem_op; // 若是值爲正數,加到現有信號量內含值中,經常使用於釋放資源;爲負數,其絕對值大於信號的現值,操做阻塞,直到信號值大於或等於 sem_op 的絕對值,經常使用於資源的使用權 458 short sem_flg; // 信號操做標誌, IPC_NOWAIT 對信號的操做不能知足時 semop 不會阻塞,並當即返回,同時設定錯誤信息; C_UNDO 程序結束時,保證信號值被重設爲 semop 調用前的值,避免程序異常狀況下將資源鎖定 459 }; 460 461 struct hostent{ 462 char *h_name; // 主機的正式名稱 463 char **h_aliases; // 主機的別名 464 int h_addrtype; // 主機的地址類型 AF_INET 465 int h_length; // 主機的地址長度(對於 ip4 是 32 位) 466 char **h_addr_list; // 主機的 ip 地址列表 467 }; 468 469 struct servent{ 470 char *s_name; // 正式服務名 471 char **s_aliases; // 別名列表 472 int s_port; // 端口號 473 char *s_proto; // 使用的協議 474 }; 475 476 struct sockaddr{ // /usr/include/sys/socket.h,通常的編程中並不直接對此數據結構進行操做,而使用另外一個與之等價的數據結構sockaddr_in 477 sa_family_t sa_family; // 2字節的地址家族,如 AF_INET 478 char sa_data[14]; // protocol address 479 }; 480 481 struct sockaddr_un{ // 長度爲 110B 482 sa_family_t sun_family; 483 char sun_path[108]; 484 }; 485 486 struct sockaddr_in{ // 長度爲 16B 487 sa_family_t sin_family; // 在 socket 編程中只能是 AF_INET 488 in_port_t sin_port; 489 struct in_addr sin_addr; 490 unsigned char sin_zero[sizeof(struct sockaddr) - (sizeof(unsigned short int)) - sizeof(in_port_t) - sizeof(struct in_addr)]; // 長度爲 8B,暫時未用,應初始化爲 0,爲了讓 sockaddr 與 sockaddr_in 兩個數據結構保持大小相同而保留的空字節。 491 }; 492 493 struct in_addr{ // <arpa/inet.h> 494 in_addr_t s_addr; // 點分十進制轉換爲的二進制數,32 位的 IPv4 地址 495 }; 496 497 struct linger{ // /usr/include/sys/socket.h 498 unsigned short l_onoff; 499 unsigned short l_linger; 500 }; 501 502 struct msghdr{ 503 void *msgname; 504 int msg_name_len; 505 struct iovec *msg_iov; 506 int msg_iovlen; 507 void *msg_control; 508 int msg_controllen; 509 int msg_flags; 510 }; 511 512 struct iovec{ 513 void *iov_base; // 緩衝區開始地址 514 size_t iov_len; // 緩衝區長度 515 }; 516 517 struct file { 518 /* 519 * fu_list becomes invalid after file_free is called and queued via 520 * fu_rcuhead for RCU freeing 521 */ 522 union { 523 struct list_head fu_list; 524 struct rcu_head fu_rcuhead; 525 } f_u; 526 struct path f_path; 527 #define f_dentry f_path.dentry 528 #define f_vfsmnt f_path.mnt 529 const struct file_operations *f_op; 530 atomic_t f_count; 531 unsigned int f_flags; 532 mode_t f_mode; 533 loff_t f_pos; 534 struct fown_struct f_owner; 535 unsigned int f_uid, f_gid; 536 struct file_ra_state f_ra; 537 unsigned long f_version; 538 #ifdef CONFIG_SECURITY 539 void *f_security; 540 #endif 541 /* needed for tty driver, and maybe others */ 542 void *private_data; 543 #ifdef CONFIG_EPOLL 544 /* Used by fs/eventpoll.c to link all the hooks to this file */ 545 struct list_head f_ep_links; 546 spinlock_t f_ep_lock; 547 #endif /* #ifdef CONFIG_EPOLL */ 548 struct address_space *f_mapping; 549 }; //Linux 2.6.11內核,文件結構體表明一個打開的文件,系統中的每一個打開的文件在內核空間都有一個關聯的struct file。它由內核在打開文件時建立,並傳遞給在文件上進行操做的任何函數。在文件的全部實例都關閉後,內核釋放這個數據結構。 550 551 552 553 基礎 554 555 556 文件描述符範圍是 0~OPEN——MAX 早期爲 19(每一個進程打開20個文件),如今多爲256。 557 558 POSIX 標只能是 Unix 中最流行的應用編程界面標準。 559 560 文件結束符 ctrl d , EOF is -1(int),不在任何頭文件中定義,應該是 liunx 默認的宏。 561 562 563 文件描述符本質是數組下標,若是子進程不打算使用父進程打開的文件,應該在調用 fork 後關閉該文件;若是父子進程同時打開一個文件,父進程讀取文件後,子進程將讀取同一文件的後續內容。而兩個進程獨立讀取同一文件時,不會相互干擾。 564 565 內核支持文件描述符的數據結構中,最右邊的是 i 節點表,整個系統只有一張,可視爲結構體數組,每一個元素對應一個物理文件;中間的是文件表,整個系統一張,可視爲結構體數組,元素中有 3 個重要的字段,指定文件被打開時採用的選項,文件當前讀寫位置,指向 i 節點表的指針(關聯物理文件);左側的表是文件描述符表,每一個進程一張,可視爲指針數組,指向文件表中的一個元素,記錄打開的文件。 566 567 extern char **environ; 指向系統環境變量的指針 568 569 刷新 I/O 緩存條件:用戶空間的 I/O 庫緩存被填滿;I/O 緩存庫遇到換行符,而且目標是行緩衝設備(屏幕);I/O 流被關閉。調用系統調用(如 write )能夠將 I/O 緩存庫內容提交給內核。 570 571 572 進程內存佈局圖:初始數據段data包含已初始化的全局變量和局部靜態變量;bbs存放的是未初始化全局變量和未初始化的static局部變量,他們初始值都爲0;stack存放的是動態局部變量,heap是malloc分配的空間;之因此子函數不能相互訪問對方動態局部變量是由於 main 函數調用 A 函數後再調用 B 函數將覆蓋 A 函數的動態局部變量存儲空間。 573 574 進程組、對話期、控制終端:對話期是一個或多個進程組的集合,創建與控制終端鏈接的對話期首進程叫做控制進程;若是對話期首進程調用 open 打開第一個還沒有與一個對話期相關聯的終端設備時沒有指定 O_NOCTTY ,此終端設備則分配給此對話期,如打開 /dev/tty 。 575 576 通常來講,收到 SIGCHLD 後,父進程會使用 wait 系統調用以取得子進程的退出狀態,而後內核就能夠從內存中釋放已結束的子進程的 PCB;而如若父進程沒有這麼作的話,子進程的 PCB 就會一直駐留在內存中,也即成爲殭屍進程。 577 孤兒進程則是指父進程結束後仍在運行的子進程。在類UNIX系統中,孤兒進程通常會被 init 進程所「收養」,成爲 init 的子進程。 578 爲避免產生殭屍進程,實際應用中通常採起的方式是: 579 1.將父進程中對 SIGCHLD 信號的處理函數設爲 SIG_IGN (忽略信號); 580 2. fork 兩次並殺死一級子進程,令二級子進程成爲孤兒進程而被 init 所「收養」、清理。 581 582 583 進程間通訊包括信號、無名管道、有名管道、共享內存、信號量、消息隊列。 584 585 操做共享內存相似於操做字符指針,用下標來讀寫。 586 587 信號量和互斥鎖,信號量爲 1 時就是互斥鎖。 588 589 每一個進程都有一個信號掩碼,用來定義被阻塞遞送的信號集合,阻塞信號在關鍵代碼執行完後才處理信號。 590 591 592 gcc 編譯線程時使用 -l pthread ,在 /usr/lib/libpthread.so 中。 593 594 輕進程( LWP )即內核線程,CPU 時間片調度是面向輕進程的,位於系統層和用戶層之間,系統經過輕進程實現對線程資源的分配、對線程的控制,一個輕進程控制一個或多個線程。 595 596 597 網絡中的 3 次握手和 4 分節終止序列。 598 599 小端系統( little endian )中變量的高位存放在高地址,大端系統中變量的高位存放在低地址,網絡中傳送的是大端字節。 600 601 流式套結字採用 TCP 協議,數據報套結字採用 UDP 協議,原始套結字容許對底層協議(如 ip 或 icmp )直接訪問,經常使用於新的網絡協議的測試等。 602 603 socket 組成爲:協議,本地地址,本地端口,遠程地址,遠程端口。 604 605 TCP 網絡編程模型 606 服務器編程模型: socket -> bind -> listen -> accept -> read -> write -> close 607 客戶端編程模型: socket -> connet -> write -> read -> close 608 服務器編程模型: socket 創建無任何網絡鏈接的 socket ,返回值是一個文件描述符 -> bind 將 socket 和本機 ip 地址和端口號綁定( 3 元組) -> listen 將 socket 指定爲一個監聽套結字,用於監聽客戶端到達的網絡鏈接請求 -> accept 使 socket 進入網絡鏈接狀態,服務器能接收客戶端鏈接,沒有鏈接則阻塞,其返回另外一個 socket ,被稱爲鏈接套結字,是一個 5 元組 -> read 讀客戶端發送的數據,不然阻塞 -> write -> close 609 客戶端編程模型: socket -> connet 將服務器 IP 和端口號做爲參數傳入,本機選擇一個未使用且大於 1024 的端口號做爲本地端口,發起鏈接,創建鏈接 -> write -> read -> close 610 611 迭代服務器一次只能處理一個客戶請求,併發服務器使用多個進程(線程)處理客戶鏈接。併發服務器的一個問題是子進程結束了而父進程還在,會累積殭屍進程,解決方法是子進程結束後給父進程發送 SIGCHLD 信號,父進程在信號處理程序中調用 waitpid 銷調子進程。 612 613 UDP 編程模型 614 服務器: socket -> bind -> recvfrom -> sendto -> close 615 客戶端: socket -> sendto -> recvfrom -> close 616 617 618 619 實踐 620 621 622 判斷條件時「if(( flag = open( "./hel.c", O_RDONLY ))< 0);」 等價於 「if( open( "./hel.c", O_RDONLY )< 0);」, 623 可是 if( flag = open( "./hel.c", O_RDONLY )< 0); is wrong. 624 625 626 程序打開的文件的讀寫權限要基於文件自己的讀寫權限。 627 628 629 time()函數的使用; 630 631 632 633