linux/unix編程手冊-6_10


title: linux/unix編程手冊-6_10 date: 2018-05-15 11:53:07 categories: programming tags: tips

linux/unix編程手冊-6(進程)

進程和程序

  • 程序:linux

    • 二進制格式標誌:最初:a.out,COFF; 現:UNIX實現採用ELF(可執行連接格式)
    • 機器語言指令
    • 程序入口地址
    • 數據
    • 符號表及重定位表
    • 共享庫和動態連接信息
    • 其餘
  • 進程shell

    • 內核定義的抽象實體,併爲該實體分配用以執行程序的各項系統資源
    • 用戶內存空間(代碼和使用的變量)
    • 一系列內核數據結構構成(維護進程狀態的信息)

進程號

#include<unistd.h>

pid_t getpid(void);

pid_t getppid(void);

//pid 的最大值爲32767, 一旦分配到32767 計數器會置爲300從新分配 
//pid_max:/proc/sys/kernel/pid_max

// /proc/$PID/status

//pstree
複製代碼

進程的內存佈局

  • 文本段(text):包含進程運行的程序指令,只讀,文本段共享,映射到全部使用進程的虛擬地址空間
  • 初始化數據包段(data):包含顯式初始化的全局變量和靜態變量
  • 未初始化數據包段(BSS段):未初始化的全局變量和靜態變量,啓動前,本段全部內存初始化0;和前者分開的緣由是程序在磁盤存儲時,不須要爲未初始化的變量分配存儲空間

$ size a.out  
   text    data     bss     dec     hex filename  
   1317     500      24    1841     731 a.out
// + + = 
複製代碼
extern char etext, edata, end;
複製代碼

虛擬內存

程序的局部性編程

  • 空間局部性:程序傾向訪問訪問過內存地址附近的內存
  • 時間局部性:程序傾向訪問已經訪問過的內存

內核爲進程分配和釋放頁表bash

進程虛擬地址空間頁——頁表——RAM頁幀數據結構

32位通常虛擬內存每頁4K, 64位?佈局

環境變量

子進程繼承父進程環境變量,並隔離ui

/proc/$PID/environ 
複製代碼
#include<stdlib.h>

extern char **environ;

char *getenv(const char *name);
    
int putenv(char *string);
// string 指向 'name=value'的字符串 修改string 會影響environ
    
int setenv(const char *name, const char *value, int overwrite);
// 將 name, value 分配至內存緩衝區,以後修改不會影響environ

int unsetenv(const char *name);
複製代碼

環境不只能夠做爲進程間通信;還能夠做爲程序間通信的方式spa

非局部跳轉

#include<setjmp.h>

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

// 調用setjmp 時,把當前進程環境的各類信息,和程序計數器(指向代碼)和棧指針寄存器的信息的副本保存到env

register int rvar;
volatile int vvar;
複製代碼

linux/unix編程手冊-7(內存分配)

堆內存

  • program break 開始位於 &end
#include <unistd.h>
int brk(void *end_data_segment);
//Returns 0 on success, or –1 on error
//設置 program break 到 end_data_segment 會根據頁四捨五入取整

void *sbrk(intptr_t increment);
//Returns previous program break on success, or (void *) –1 on error
//設置 program break 增長 increment
複製代碼
#include<stdlib.h>
#include<malloc.h>
void *malloc(size_t size);
//Returns pointer to allocated memory on success, or NULL on error 不初始化內存

void free(void *ptr);
// free通常不會下降program break, 可是當棧頂的空閒內存足夠大,free的glibc實現會調用sbrk來下降program break

void *calloc(size_t numitems, size_t size);
//Returns pointer to allocated memory on success, or NULL on error 初始化爲0

void *realloc(void *ptr, size_t size);
//Returns pointer to allocated memory on success, or NULL on error 無連續的內存,拷貝至新內存

void *memalign(size_t boundary, size_t size);
//Returns pointer to allocated memory on success, or NULL on error 起始地址參數是boundary的整數倍

複製代碼

棧內存

#include <alloca.h>
void *alloca(size_t size);
//Returns pointer to allocated block of memory
複製代碼

linux/unix編程手冊-8(用戶和組)

Linux 用戶ID能夠不惟一對應多個用戶名unix

#include <pwd.h>
struct passwd {
        char *pw_name;
        char *pw_passwd;
        uid_t pw_uid;
        gid_t pw_gid;
        char *pw_gecos;
        char *pw_dir;
        char *pw_shell;
};

struct passwd *getpwnam(const char *name);
struct passwd *getpwuid(uid_t uid);
//Both return a pointer on success, or NULL on error; see main text for description of the 「not found」 case
// 返回的指針指向靜態內存,不可重入(not reentrant)


複製代碼
#include <grp.h>
struct group {
    char  *gr_name;
    char  *gr_passwd;
	gid_t  gr_gid;
	char **gr_mem;
};
struct group *getgrnam(const char *name);
struct group *getgrgid(gid_t gid);
//Both return a pointer on success, or NULL on error; see main text for description of the 「not found」 case
// 返回的指針指向靜態內存,不可重入(not reentrant)

複製代碼

linux/unix編程手冊-9(進程憑證)

  • 實際用戶/組ID(real xx id)指針

    • 進程所屬的用戶組,子進程繼承自父進程
  • 有效用戶/組ID(effective xx id)

    • 一般有效用戶/組ID和實際用戶/組ID相同,可是有兩種方法致使不一樣

      • xxx

      • 執行set-user-ID 和 set-group-ID的程序

        • # ls -l prog
          -rwxr-xr-x 1 root root 302585 Jun 26 15:05 prog
          # chmod u+s prog //Turn on set-user-ID permission bit
          # chmod g+s prog //Turn on set-group-ID permission bit
          # ls -l prog
          -rwsr-sr-x 1 root root 302585 Jun 26 15:05 prog
          複製代碼
        • 會將可執行權限x標識改成s

        • 對於shell腳本無效(38.3補充)

    • 有效用戶ID=0的進程擁有root權限,稱之爲特權級進程

  • 保存的用戶/組ID(saved set-xx-id)

    • 配合set-user-ID 和 set-group-ID使用
    • 其值爲複製的有效用戶/組ID
    • 一些系統調用將標識S的進程的有效用戶ID在實際和保存ID間切換
  • 文件系統用戶/組ID(file-system xx id)

    • linux中對於文件的系統操做的權限是由文件系統ID(結合輔助組ID)決定的
    • 通常來講文件系統ID等於有效用戶ID,不管是系統調用仍是設置了set-user-ID位,文件系統ID都會變成同一值,只有特殊的setfsuid(),setfsgid()纔會使不一致
  • 輔助組ID

#include<unistd.h>
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);

// 修改有效xxID 調用 ,均返回0:success, -1:fail
int setuid(uid_t uid);
int setgid(gid_t gid);

int seteuid(uid_t uid);
int setegid(gid_t gid);
複製代碼
  • 非特權進程調用setuid
    • 僅能修改有效用戶ID,
    • 且僅能修改成實際的用戶ID和保存用戶ID
    • setuid等效於seteuid
  • 特權進程調用以一個非0參數x調用setuid,
    • 用戶的3個id均會變爲x,且再也不是特權進程,不可逆
    • 調用seteuid只改變euid,能夠以非特權的規則恢復
#include<unistd.h>
// uid, euid爲-1是不修改
int setreuid(uid_t ruid, uid_t euid);
int setregid(gid_t rgid, gid_t egid);
複製代碼
  • 非特權進程可
    • 將ruid 設爲 當前ruid, euid
    • 將euid設爲 當前ruid, euid, suid
  • 特權進程可
    • 將ruid設爲任意值
    • 將euid設爲任意值
  • 知足如下之一suid會設爲euid:
    • ruid不爲-1
    • euid值不等於原ruid值
  • 注意調用順序,修改了uid以後gid可能沒法修改

相似略

linux/unix編程手冊-10(時間)

  • 真實時間
  • 進程時間(進程建立後使用cpu的時間)
    • 用戶CPU時間
    • 系統CPU時間
//系統時區 連接到/usr/share/zoninfo的某文件
$ ll /etc/localtime
lrwxrwxrwx 1 root root 25 5月   2 22:36 /etc/localtime -> ../usr/share/zoneinfo/UTC
複製代碼
$ locale
LANG=en_US.UTF-8
LC_CTYPE=zh_CN.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
複製代碼
//修改環境變量執行
$ LANG=de_DE ./show_time  
複製代碼

軟件時鐘(jiffies), linux時間精度取決於jiffies 時鐘頻率100,250,1000Hz 對應jiffies(10,4,1ms)

相關文章
相關標籤/搜索