日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux系统编程--2(环境变量,进程控制)

發布時間:2023/11/30 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程--2(环境变量,进程控制) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

環境變量

環境變量

是指在操作系統中用來指定操作系統運行環境的一些參數
每個人用電腦的習慣不一樣,比如一般把文件放到磁盤,怎么管理文件,用什么編譯器,所以,環境變量就是根據每個人使用操作系統的習慣來規定一些參數

具體特征

  • 字符串(本質)
  • 有統一的格式:名=值[:值]
  • 值用來描述進程環境信息
  • 存儲形式:

    與命令行參數類似。char*[]數組,數組名 environ,內部存儲字符串,NULL 作為哨兵結尾。

    使用形式:

    與命令行參數類似。

    加載位置:

    與命令行參數類似。位于用戶區,高于 stack 的起始位置。 引入環境變量表:須聲明環境變量。externchar**environ;

    打印當前進程的所有環境變量

    常見環境變量

    按照慣例,環境變量字符串都是 name=value 這樣的形式,大多數 name 由大寫字母加下劃線組成,一般把 name 的部分叫做環境變量,value 的部分則是環境變量的值。

    PATH

    可執行文件的搜索路徑。ls 命令也是一個程序,執行它不需要提供完整的路徑名/bin/ls,然而通常我們執行當 前目錄下的程序 a.out 卻需要提供完整的路徑名./a.out,這是因為 PATH 環境變量的值里面包含了 ls 命令所在的目錄 /bin,卻不包含 a.out 所在的目錄。PATH 環境變量的值可以包含多個目錄,用:號隔開。在 Shell 中用 echo 命令可以 查看這個環境變量的值:

    $echo$PATH


    shell解析器按照PATH環境變量中已經設定好的目錄,一個目錄一個目錄找

    SHELL

    當前 Shell,它的值通常是/bin/bash。

    TERM

    當前終端類型,在圖形界面終端下它的值通常是 xterm,終端類型決定了一些程序的輸出顯示方式,比如圖形 界面終端可以顯示漢字,而字符終端一般不行。

    LANG

    語言和 locale,決定了字符編碼以及時間、貨幣等信息的顯示格式。

    HOME

    當前用戶主目錄的路徑,很多程序需要在主目錄下保存配置文件,使得每個用戶在運行該程序時都有自己的一套配置。

    環境變量的相關函數

    getenv 函數

    獲取環境變量值

    chargetenv(constcharname); 成功:返回環境變量的值;失敗:NULL(name 不存在)

    setenv 函數

    設置環境變量的值

    intsetenv(constcharname,constcharvalue,intoverwrite); 成功:0;失敗:-1
    參數 overwrite 取值: 1:覆蓋原環境變量 0:不覆蓋。(該參數常用于設置新環境變量,如:ABC=haha-day-night)

    unsetenv 函數

    刪除環境變量 name 的定義

    intunsetenv(constchar*name); 成功:0;失敗:-1
    注意事項:name 不存在仍返回 0(成功),當 name 命名為"ABC="時則會出錯。

    測試代碼

    #include<stdio.h> #include<stdlib.h> #include<string.h>int main(void) {char *val;const char *name="ABD";//從當前的環境變量表中獲得名字為name的環境變量值,保存到val里val=getenv(name);printf("1, %s = %s\n",name,val);//獲取不出來,出一個空值//覆蓋原有的環境變量setenv(name,"haha-day-and-night",1);//再獲取環境變量val=getenv(name); printf("2, %s = %s\n",name,val);//刪除剛添加的ABDint ret=unsetenv("ABD");//name=value:valueprintf("ret= %d\n",ret); val=getenv(name);printf("3, %s = %s\n",name,val);return 0; }

    #include<stdio.h> #include<stdlib.h> #include<string.h>int main(void) {char *val;const char *name="ABD";//從當前的環境變量表中獲得名字為name的環境變量值,保存到val里val=getenv(name);printf("1, %s = %s\n",name,val);//獲取不出來,出一個空值//覆蓋原有的環境變量setenv(name,"haha-day-and-night",1);//再獲取環境變量val=getenv(name);printf("2, %s = %s\n",name,val);#if 1int ret=unsetenv("ABDFGH");//name=value:valueprintf("ret= %d\n",ret);val=getenv(name);printf("3, %s = %s\n",name,val);#else//刪除剛添加的ABDint ret=unsetenv("ABD");//name=value:valueprintf("ret= %d\n",ret); val=getenv(name);printf("3, %s = %s\n",name,val); #endif return 0; }

    進程控制

    fork 函數

    創建一個子進程。一個進程–>2個進程—>各自對fork做返回
    pid_tfork(void); 失敗返回-1;成功返回:
    ① 父進程返回子進程的 ID(非負整數>0,父進程)
    ②子進程返回 0 pid_t 類型表示進程 ID,但為了表示-1,它是有符號整型。(0 不是有效進程 ID,init 最小,為 1),返回值=0,是子進程
    注意返回值,不是 fork 函數能返回兩個值,而是 fork 后,fork 函數變為兩個,父子需【各自】返回一個

    getpid 函數

    獲取當前進程 ID
    pid_tgetpid(void);

    getppid 函數

    獲取當前進程的父進程 ID
    pid_tgetppid(void);
    區分一個函數是“系統函數”還是“庫函數”依據:

  • 是否訪問內核數據結構
  • 是否訪問外部硬件資源 二者有任一 → 系統函數;二者均無 → 庫函數
  • getuid 函數

    獲取當前進程實際用戶 ID
    uid_tgetuid(void);
    獲取當前進程有效用戶 ID
    uid_tgeteuid(void);

    getgid 函數

    獲取當前進程使用用戶組 ID
    gid_tgetgid(void);
    獲取當前進程有效用戶組 ID
    gid_tgetegid(void);

    創建子進程

    #include<stdio.h> #include<unistd.h> #include<stdlib.h>int main() {pid_t pid;printf("xxxxxxxxxxxxxx\n");pid=fork();if(pid==-1){ perror("fork error");exit(1);} else if(pid==0){ printf("I am child\n,pid= %u, ppid= %u\n",getpid(),getppid());} else{ printf("I am parent\n,pid= %u, ppid= %u\n",getpid(),getppid());sleep(1);} //這段代碼父子進程都有,所以要打印兩次printf("yyyyyyyyyyyyyyyyyyy\n"); }


    循環創建 n 個子進程

    一次 fork 函數調用可以創建一個子進程。那么創建 N 個子進程應該是for(i=0;i<n;i++){fork()} 。但這樣創建的并非是N個子進程

    當 n 為 3 時候,循環創建了(2^n)-1 個子進程,而不是 N 的子進程。需要在循 環的過程,保證子進程不再執行 fork ,因此當(fork()==0)時,子進程應該立即 break;才正確。

    #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() {int i;//循環因子pid_t pid;printf("xxxxxxxxxxxxxx\n");for(i=0;i<5;i++){pid=fork();if(pid==-1){perror("fork error");exit(1);}else if(pid==0){break;// printf("I am %d child\n,pid= %u, ppid= %u\n",i+1 ,getpid(),getppid());}else{// printf("I am parent\n,pid= %u, ppid= %u\n",getpid(),getppid());// sleep(1);}}if(i<5){sleep(i);printf("I am %d child %u\n",i+1,getpid());}else{sleep(i);printf("I am parent\n");}return 0; }

    進程共享

    父子進程之間在 fork 后。有一些相同與不同的地方

    父子相同處

    剛 fork 之后: 父子相同處:

  • 全局變量、.
  • data、
  • text、
  • 棧、
  • 堆、
  • 環境變量、
  • 用戶 ID、
  • 宿主目錄、
  • 進程工作目錄、
  • 信號處理方式…
  • 父子不同處:

  • 進程 ID
  • fork 返回值
  • 父進程 ID
  • 進程運行時間
  • 鬧鐘(定時器)
  • 未決信號集
    似乎,子進程復制了父進程 0-3G 用戶空間內容,以及父進程的 PCB,但 pid 不同。真的每 fork 一個子進程都要 將父進程的 0-3G 地址空間完全拷貝一份,然后在映射至物理內存嗎?
    當然不是!父子進程間遵循讀時共享寫時復制(共享一塊物理地址空間)的原則。這樣設計,無論子進程執行父進程的邏輯還是執行自己 的邏輯都能節省內存開銷。
  • 注意

    全局變量各自是獨立的不能共享

    重點:

    父子進程共享:

  • 文件描述符(打開文件的結構體)
  • mmap 建立的映射區 (進程間通信詳解)
    特別的,fork 之后父進程先執行還是子進程先執行不確定。取決于內核所使用的調度算法。(隨機爭奪)
  • gdb 調試

    使用 gdb 調試的時候,gdb 只能跟蹤一個進程。可以在 fork 函數調用之前,通過指令設置 gdb 調試工具跟蹤父 進程或者是跟蹤子進程。默認跟蹤父進程。
    set follow-fork-mode child 命令設置 gdb 在 fork 之后跟蹤子進程。
    set follow-fork-mode parent 設置跟蹤父進程。
    注意,一定要在 fork 函數調用之前設置才有效。

    list 展示代碼 l 顯示剩余代碼 gcc 文件名 -g gdb a.out start/run按什么方式往下走(run自動,start逐步) next/n往下走 quit退出 b 行數 if 條件 //設置條件斷點 info b //查看斷點

    總結

    以上是生活随笔為你收集整理的Linux系统编程--2(环境变量,进程控制)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。