APUE 進程環(huán)境

本文使用golang的syscall,os,golang.org/x/sys/unix包

1.main函數(shù)

main是程序的入口,golang中也亦是如此
啟動一個程序時啟動例程負責從內核獲取命令行參數(shù)和環(huán)境變量,維護到程序的內存布局中(后文描述)

2.exit

//import os
func Exit(code int)

使程序主動退出,令退出碼為指定值code,程序正常結束時返回碼為0 (在一般的shell中使用$?獲取)

  • 執(zhí)行exit時 會使標準I/O進行關閉flush操作
  • APUE中提到針對C語言,C99之前main終止前沒有顯式return或exit會導致退出嗎不確定

atexit函數(shù),golang中未實現(xiàn)

#include<stdlib.h>
int atexit(void (*func)(void)));

3.命令行參數(shù)

//import os
var Args []string

程序啟動時命令行跟隨的參數(shù)

4.C程序的存儲空間布局

space
  • 正文段:CPU執(zhí)行的機器指令,該部分使可共享的,只讀的
  • 初始化數(shù)據(jù)段: 包含了程序明確賦初值的變量,如C中已賦值的全局變量
  • 未初始化的數(shù)據(jù)段:該段在程序啟動前,由內核將此段中數(shù)據(jù)刷為0(該段不部存放在磁盤文件中)
  • 堆:運行時,動態(tài)存儲分配的資源位置
  • 棧:運行時,自動變量以及函數(shù)調用時所需保存的信息都存于此處
  • 高地址部分:存儲命令行參數(shù)和環(huán)境變量

shell中可使用size命令查看二進制程序的正文段,初始化段,bss段

5.共享庫

操作系統(tǒng)所支持的一種庫操作,使得程序與存儲中的共享庫連接,減小了程序的大小,但略微增加了程序執(zhí)行開銷(在程序第一次運行或每個共享庫第一次被調用)

golang共享庫 待補充。。

6.存儲空間分配

原文中提到的是malloc caloc realloc,實際在golang中應使用make new

//builtin
func make(t Type, size ...IntegerType) Type
func new(Type) *Type

7.環(huán)境變量

//import golang.org/x/sys/unix
func Getenv(key string) (value string, found bool) {
    return syscall.Getenv(key)
}

func Setenv(key, value string) error {
    return syscall.Setenv(key, value)
}

[4.C程序的存儲空間布局],我們已知環(huán)境變量在棧之上(進程存儲空間頂部),且由一個**char的指針列表來維護,且該空間不可伸縮,當要新增環(huán)境變量時會導致一些存儲變化

分3種情況討論

  • 刪除一個環(huán)境變量:直接刪除其環(huán)境列表中的指針,后續(xù)指針順次前移
  • 修改一個環(huán)境變量:
    • 修改后值變小:直接修改原key=value值
    • 修改后值變大: 需要在堆中新分配一個存儲空間村kv,再修改指針表中其對應地址
  • 增加一個環(huán)境變量:
    • 第一次增加:再堆中分配一個空間存儲新的環(huán)境表,將老的環(huán)境表拷貝過來,然后在尾部追加本次待插入的key=value的指針和一個空指針,再將內核的environ指向該指針表
    • 非第一次添加:realloc指針表,同上在尾部追加(原表尾會又一個空指針,利用這個)一個kv值的指針和一個空指針

8.setjmp,longjmp

C中跨越函數(shù)goto的高級玩法,通常適用于一些深層嵌套的函數(shù)

#include<sethmp.h>

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);

jmp_buf變量通常使用全局變量,是一個某種形式的數(shù)組,存儲恢復棧狀態(tài)時所需要的信息。

longjmp回跳時需要提供這個buf以便找到要恢復的位置。
longjmp還需要提供一個整型值,以通知setjmp的返回值,直接調用setjmp返回的值為0
longjmp后會拋棄掉調用setjmp的函數(shù)棧幀一下的所有棧幀

關于longjmp后變量值的問題:存放在存儲器中的值(通常為內存)保持longjmp時的值,而cpu和浮點寄存器的值恢復到setjmp時的狀態(tài)

9.資源限制

type Rlimit struct {
    Cur uint64 //soft limit
    Max uint64 //hard limit
}

func Getrlimit(resource int, rlim *Rlimit) (err error)
func Setrlimit(resource int, rlim *Rlimit) (err error)

Cur決定當前實際的限制值
關于rlimit結構,存在3個規(guī)則:

  • 任何一個進程都可以更改Cur小于等于Max

  • 任何一個進程都可以降低Max,但必須大于等于Cur,對非root是不可逆的

  • root可調大Max

    resource 含義

    //golang.org/x/sys/unix CONST

    resource 含義

|RLIMIT_AS | 0x9|進程可用存儲空間最大值|
|RLIMIT_CORE | 0x4|core文件最大字節(jié)數(shù),0則阻止創(chuàng)建core文件|
| RLIMIT_CPU | 0x0|CPU時間最大量值,超過則發(fā)送SIGXCPU信號|
| RLIMIT_DATA | 0x2|數(shù)據(jù)段最大字節(jié)長度(初始化,RSS,堆)|
| RLIMIT_FSIZE | 0x1|可創(chuàng)建文件最大字節(jié)長度|
| RLIMIT_LOCKS | 0xa|一個進程可持有的文件鎖的最大數(shù)|
| RLIMIT_MEMLOCK | 0x8|使用MLOCK能鎖住的最大字節(jié)長度空間|
| RLIMIT_MSGQUEUE | 0xc|POSIX消息隊列最大存儲字節(jié)長度|
| RLIMIT_NICE | 0xd|Nice值可設置最大值|
| RLIMIT_NOFILE | 0x7|能打開的最大句柄數(shù)|
| RLIMIT_NPROC | 0x6|每個實際用戶ID可擁有最大進程數(shù)|
| RLIMIT_RSS | 0x5|RSS最大長度|
| RLIMIT_RTPRIO | 0xe|進程可通過sched_setscheduler 和 sched_setparam設置的最大實時優(yōu)先級。
| RLIMIT_RTTIME | 0xf|CPU時間限制,在非阻塞系統(tǒng)調用上的CPU時間消耗,到soft值時會收到SIGXCPU,超過hard值時會收到SIGKILL
| RLIMIT_SIGPENDING | 0xb|一個進程可排隊的最大信號數(shù)量|
| RLIMIT_STACK | 0x3|棧的最大字節(jié)長度|
| RLIM_INFINITY | -0x1|無限量值|

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容