国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Linux > 正文

《Linux/Unix系統編程手冊》讀書筆記3

2024-06-28 13:26:52
字體:
來源:轉載
供稿:網友
《linux/Unix系統編程手冊》讀書筆記3

《Linux/Unix系統編程手冊》讀書筆記 目錄

第6章

這章講進程、虛擬內存和環境變量等。

進程是一個可執行程序的實例。一個程序可以創建很多進程。

進程是由內核定義的抽象實體,內核為此實體分配執行程序所需的系統資源。

從內核的角度來看,進程是由用戶內存空間和內核數據結構組成的。程序的代碼和代碼中的變量存放在用戶內存空間,內核數據結構用于維護進程狀態信息。

對于每個進程都有一個唯一的進程號(進程ID)(正數),用來標識系統中的某個程序。

getpid(),返回調用該函數的進程的進程ID。

1 #include <unistd.h>2 3 pid_t getpid(void);

總是成功調用并返回調用該函數的進程的進程ID。

getppid(),返回自己的父進程的進程ID。

1 #include <unistd.h>2 3 pid_t getppid(void);

總是成功調用并返回該函數的父進程的ID。

PS:所有進程的始祖為init進程(進程ID為1)。

內存布局:

Linux/x86-32進程內存結構如下:

文本段存放著程序運行的機器語言指令,具有只讀屬性,防止進程通過錯誤指針修改自身指令。

初始化數據段存在著顯式初始化的全局變量和靜態變量。

未初始化數據段存放著未進行顯式初始化的全局變量和靜態變量。將已經初始化的全局變量和靜態變量與未進行初始化的全局變量和靜態變量分開存放是因為程序在存放在磁盤上沒有必要為未初始化的變量分配存儲空間,只需要記錄未初始化數據段的位置和大小,在程序運行的時候再分配空間。

堆(heap)是在運行時為變量動態進行內存分配的區域,堆頂叫PRogram break,后面一章就是通過brk()和sbrk()來調整堆的大小進而來分配內存(malloc()就是基于這兩個函數實現)。

棧(stack)由棧幀組成的,可以動態增長和收縮的段,系統為每個當前調用的函數分配一個棧幀,里面存儲了函數的局部變量(自動變量)。

通過虛擬內存管理技術可以高效的使用CPU和RAM資源。因為大多數都有兩個局部性:空間局部性和時間局部性。

虛擬內存將每個程序使用的內存分割成小塊、固定大小的頁單元。對于RAM,將其劃分成一系列與虛擬內存頁面大小相同的頁幀。在程序運行的時候,只有一部分的頁駐留在物理內存頁幀中,當進程需要訪問的頁面不在物理內存中,就會發生頁面錯誤,并掛起進程的執行,再將頁面從磁盤載入到物理內存。

內核為每個進程維護一張頁表,通過頁表可以虛擬地址對應的物理地址。

虛擬內存的實現需要硬件有分頁內存管理單元(將虛擬內存地址轉成相應的物理內存地址)。

通過虛擬內存管理可以將虛擬地址空間與RAM物理地址空間隔開:使進程與進程、進程與內核相互隔離,可以保護進程和內核的內存;可以使得多個進程共享內存;實現內存保護機制;程序員和一些程序無需關注程序在物理內存的布局;還可以提高CPU利用率。

命令行參數:

int argc; 命令行參數個數;

char *argv[];指向命令行參數的指針數組;

PS:這兩個參數是main()函數的局部變量,所以其他函數要使用這兩個參數需要進行傳遞或者設置一個指向argv的全局變量。

環境列表:

每個進程都有與自己相關的環境列表。

每條記錄的形式為name=value;

新進程創建時會繼承父進程的環境副本(原始的進程間通信方式)。

可以通過printenv輸出當前的環境列表:

 1 lancelot@debian:~$ printenv 2 SSH_AGENT_PID=4370 3 CLUTTER_IM_MODULE=ibus 4 GPG_AGENT_INFO=/home/lancelot/.cache/keyring-A5CMa0/gpg:0:1 5 TERM=xterm 6 SHELL=/bin/bash 7 XDG_session_COOKIE=66aede8f90c2ace983c1e18451c8875a-1397554660.783480-1822251707 8 HUSHLOGIN=FALSE 9 GNOME_KEYRING_CONTROL=/home/lancelot/.cache/keyring-A5CMa010 LC_ALL=zh_CN.UTF-811 USER=lancelot12 LIBGL_DRIVERS_PATH=/usr/lib/i386-linux-gnu/dri:/usr/lib/x86_64-linux-gnu/dri13 LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:14 DESKTOP_AUTOSTART_ID=10dc1ad7011f06891f13975546639294040000004379000115 SSH_AUTH_SOCK=/home/lancelot/.cache/keyring-A5CMa0/ssh16 SESSION_MANAGER=local/debian:@/tmp/.ICE-unix/4379,unix/debian:/tmp/.ICE-unix/437917 PATH=/home/lancelot/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/lancelot/bin18 MAIL=/var/mail/lancelot19 LC_COLLATE=C20 PWD=/home/lancelot21 XMODIFIERS=@im=ibus22 LANG=zh_CN.UTF-823 HOME=/home/lancelot24 SHLVL=225 LANGUAGE=zh_CN.UTF-8:zh:en_US:en26 GNOME_DESKTOP_SESSION_ID=this-is-deprecated27 LOGNAME=lancelot28 XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/29 QT4_IM_MODULE=ibus30 DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-q3rPwh3OMI,guid=5495fcf0de26e09259bc54ef534cfde431 WINDOWPATH=732 TEXTDOMAIN=im-config33 DISPLAY=:034 GTK_IM_MODULE=ibus35 TEXTDOMAINDIR=/usr/share/locale/36 XAUTHORITY=/home/lancelot/.Xauthority37 _=/usr/bin/printenv
View Code

getenv(),獲得進程環境的值

1 #include <stdlib.h>2 3 char *getenv(const char *name);

對于存在name的環境變量就返回對應的value的指針,如果不存在就返回NULL

putenv(),修改環境變量

1 #include <stdlib.h>2 3 int putenv(char *string);

將name=value形式的字符串添加到當前的環境列表。成功返回0,失敗返回非0值。

PS:putenv是將environ變量的某個元素指向string指向的位置,并不是指向string指向字符串的副本。所以如果修改string指向的內容,環境變量也會改變,因此string指向后來不能是自動變量。

PS:當string里不包含等號的時候,將會在環境列表移除string命名的環境變量。

setenv(),往環境添加變量

1 #include <stdlib.h>2 3 int setenv(const char *name, const char *value, int overwrite);

name,value與name=value對應,overwrite決定時候改變環境。如果以name標識的變量存在環境里而且overwrite為0,就不改變環境;否則如果overwrite不為0就總是改變環境。

成功返回0, 失敗返回-1

PS:不同與putenv,setenv是分配一塊內存緩沖區,將name和value指向的字符串復制到緩沖區里。

unsetenv(),移除環境變量

1 #include <stdlib.h>2 3 int unsetenv(const char *name);

移除name標識的變量

成功調用返回0,失敗返回-1。

clear(),清除整個環境

1 #define _BSD_SOURCE2 #include <stdlib.h>3 4 int clearenv(void);

成功調用返回0,失敗返回非0值。

PS:setenv和clearenv會導致內存泄露:setenv分配了一塊內存緩沖區,但是clearenv沒有釋放這個緩沖區。

-----------------省略setjmp()和longjump(),非局部跳轉(不同于goto,可以從一個函數跳轉到另一個函數)------------

自己比較少使用。。。。還有整整一本下冊啊。。。今天面試被虐了。。。

要繼續認真看這本書。。。后臺開發不容易做啊。。。。。。。。。。。。

----------------中間吐槽完畢-------------------------------------------------------------------------------------------------------------

練習:

6-1:編譯程序清單6-1的程序,使用ls -l 命令顯示可執行文件的大小。雖然程序包含一個大約10MB的數組,但可執行文件大小遠小于此,為什么?

程序清單如下:

 1 /* 2  * ===================================================================================== 3  * 4  *       Filename:  mem_segment.c 5  * 6  *    Description:   7  * 8  *        Version:  1.0 9  *        Created:  2014年03月19日 00時03分10秒10  *       Revision:  none11  *       Compiler:  gcc12  *13  *         Author:  alan (), alan19920626@Gmail.com14  *   Organization:  15  *16  * =====================================================================================17  */18 19 #include <stdio.h>20 #include <stdlib.h>21 22 char globBuf[65536];23 int primes[] = {2, 3, 5, 7};24 25 static int square(int x){26     int result;27 28     result = x * x;29     return result;30 }31 32 static void doCal(int val){33     printf("The square of %d is %d/n", val, square(val));34 35     if(val < 1000){36         int t;37 38         t = val * val * val;39         printf("The cube of %d is %d/n", val, t);40     }41 }42 43 int main(int argc, char *argv[]){44     static int key = 9973;45     static char mbuf[10240000];46     char *p;47 48     p = (char *)malloc(1024);49 50     doCal(key);51 52     exit(EXIT_SUCCESS);53 }
6-1

結果如下:

lancelot@debian:~/Code/tlpi$ gcc -o mem_segments mem_segment.c lancelot@debian:~/Code/tlpi$ gvim mem_segment.c lancelot@debian:~/Code/tlpi$ ls -l mem_segments-rwxr-xr-x 1 lancelot lancelot 7500  4月 15 16:00 mem_segments

因為那個10MB的數組(靜態)沒有初始化,所以是存放在未初始化的數據,只有在運行的時候再為其分配內存。

6-3:使用getenv()函數,和putenv()函數,必要時可以直接修改environ,來實現setenv()函數和unsetenv()函數。(結合6-4程序清單)

 1 /* 2  * ===================================================================================== 3  * 4  *       Filename:  6-3.c 5  * 6  *    Description:   7  * 8  *        Version:  1.0 9  *        Created:  2014年04月11日 15時30分32秒10  *       Revision:  none11  *       Compiler:  gcc12  *13  *         Author:  alan (), alan19920626@gmail.com14  *   Organization:  15  *16  * =====================================================================================17  */18 19 #define _GNU_SOURCE20 #include <stdlib.h>21 #include <string.h>22 #include "tlpi_hdr.h"23 24 extern char **environ;25 char env[1000];26 27 int M_setenv(const char *name, const char *value, int overwrite){28     strcpy(env, name);29     strcat(env, "=");30     strcat(env, value);31 32     if(getenv(name) != NULL && overwrite == 0)33         return 0;34     if(putenv(env) == 0)35         return 0;36     else37         return -1;38 }39 40 int M_unsetenv(const char *name){41     if(putenv((char *)name) == 0)42         return 0;43     return -1;44 }45 46 int main(int argc, char *argv[]){47     int j;48     char **ep;49 50     clearenv();51 52     for(j = 1; j < argc; j++)53         if(putenv(argv[j]) != 0)54             errExit("putenv: %s", argv[j]);55 56     if(M_setenv("GREET", "Hello world", 0) == -1)57        errExit("M_setenv");58 59     M_unsetenv("BYE");60 61     for(ep = environ; *ep != NULL; ep++)62         puts(*ep);63 64     exit(EXIT_SUCCESS);65 }

6-4程序清單:

 1 /* 2  * ===================================================================================== 3  * 4  *       Filename:  modify_env.c 5  * 6  *    Description:   7  * 8  *        Version:  1.0 9  *        Created:  2014年03月19日 10時48分04秒10  *       Revision:  none11  *       Compiler:  gcc12  *13  *         Author:  alan (), alan19920626@gmail.com14  *   Organization:  15  *16  * =====================================================================================17  */18 19 #define _GNU_SOURCE20 #include <stdlib.h>21 #include "tlpi_hdr.h"22 23 extern char **environ;24 25 int main(int argc, char * argv[]){26     int j;27     char **ep;28 29     clearenv();30 31     for(j = 1; j < argc; j++)32         if(putenv(argv[j]) != 0)33             errExit("putenv: %s", argv[j]);34 35     if(setenv("GREET", "Hello world", 0) == -1)36         errExit("setenv");37     38     unsetenv("BYE");39 40     for(ep = environ; *ep != NULL; ep++)41         puts(*ep);42 43     exit(EXIT_SUCCESS);44 }
View Code

結果:

lancelot@debian:~/Code/tlpi$ ./6-3 "GREET=Guten" SHELL=/bin/bash BYE=CiaoGREET=GutenSHELL=/bin/bashlancelot@debian:~/Code/tlpi$ ./6-3 SHELL=/bin/sh BYE=byebyeSHELL=/bin/shGREET=Hello world

PS:吐槽。。。。。。還要繼續努力,努力成為一個后臺開發。。。。。。。。。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 石屏县| 林州市| 洞头县| 新乐市| 景泰县| 长乐市| 铁力市| 富阳市| 阳东县| 玛纳斯县| 夏津县| 中阳县| 柳林县| 元谋县| 崇义县| 本溪| 泸溪县| 绥化市| 日土县| 牡丹江市| 阿克陶县| 林西县| 本溪市| 桂东县| 久治县| 循化| 平武县| 天峻县| 金沙县| 三都| 阿图什市| 始兴县| 明水县| 象州县| 彝良县| 嘉义市| 东光县| 永定县| 商丘市| 伊川县| 华蓥市|