linux c/c++
生活随笔
收集整理的這篇文章主要介紹了
linux c/c++
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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
?
轉載于:https://www.cnblogs.com/little-snake/p/5329138.html
總結
以上是生活随笔為你收集整理的linux c/c++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RxJava初级解析(一)
- 下一篇: Nginx 虚拟主机 VirtualHo