• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • /proc文件系統入門

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    理解/proc文件系統 理解/proc文件系統 ◆ 介紹/proc 在過去那些糟糕的日子里,只能通過直接訪問內核內存(/dev/kmem)獲取進程數據,比如運行ps(1)命令時。為了實現這種訪問,需要超級用戶權限,而且步驟相當復雜。Sun公司從 UNIX SVR4開始解決了進程數據訪問
    理解/proc文件系統

    理解/proc文件系統  

    ◆ 介紹/proc

    在過去那些糟糕的日子里,只能通過直接訪問內核內存(/dev/kmem)獲取進程數據,比如運行ps(1)命令時。為了實現這種訪問,需要超級用戶權限,而且步驟相當復雜。Sun公司從UNIX SVR4開始解決了進程數據訪問問題,現在,可以簡單地通過/proc訪問進程數據。

    /proc文件系統不是普通意義上的文件系統,它是一個到運行中進程地址空間的訪問接口。通過/proc,可以用標準Unix系統調用(比如open()、read()、write()、ioctl()等等)訪問進程地址空間。事實上,Solaris ps(1)命令正是利用/proc獲取進程狀態。

    S (l) 進程狀態:

    O 正在運行
    S 休眠: 進程正在等待某個事件發生/完成
    R 可運行: 進程位于運行隊列中
    Z 僵尸狀態: 進程結束了,但是其父進程未處理SIGCHLD信號
    T 進程暫停: 可能是任務控制信號所致,或者正在被
    跟蹤調試

    /proc下的大文件對應運行中進程的地址空間,不是標準Unix文件。事實上每個文件名對應運行中進程的PID,文件屬主、屬組對應進程擁有者的real-uid和primary-gid。權限控制與普通Unix文件一樣。文件大小是最令人迷惑的地方,事實上相當好理解,對應進程內存映像大小,并不真正占用硬盤空間,所以你不必擔心空間浪費的問題。不要企圖刪除這些文件!觀察圖A中列舉的/proc例子:

    --------------------------------------------------------------------------

    $ ls -l /proc
    total 43384
    -rw------- 1 root root 0 Apr 2 20:07 00000
    -rw------- 1 root root 393216 Apr 2 20:07 00001
    -rw------- 1 root root 0 Apr 2 20:07 00002
    -rw------- 1 root root 0 Apr 2 20:07 00003
    -rw------- 1 root root 1695744 Apr 2 20:07 00081
    -rw------- 1 root root 1597440 Apr 2 20:07 00083
    -rw------- 1 root root 1777664 Apr 2 20:08 00096
    -rw------- 1 root root 1683456 Apr 2 20:08 00099
    -rw------- 1 root root 1589248 Apr 2 20:08 00101
    -rw------- 1 root root 1445888 Apr 2 20:08 00116
    -rw------- 1 root root 1404928 Apr 2 20:08 00126
    -rw------- 1 root root 798720 Apr 2 20:08 00135
    -rw------- 1 root root 1368064 Apr 2 20:08 00195
    -rw------- 1 root root 1585152 Apr 2 20:08 00197
    -rw------- 1 root root 1368064 Apr 2 20:08 00200
    -rw------- 1 root other 225280 Apr 2 20:08 00201
    -rw------- 1 root root 1454080 Apr 2 20:08 00203
    -rw------- 1 root root 1519616 Apr 2 20:14 00243
    -rw------- 1 rthomas wheel 1499136 Apr 2 20:14 00245
    -rw------- 1 rthomas wheel 806912 Apr 2 20:16 00261
    $

    圖A: /proc例子

    --------------------------------------------------------------------------

    操作/proc下文件的方式和操作普通Unix文件一樣,可以使用所有你熟悉的系統調用,包括ioctl()。在內核中,針對/proc下文件的vnode操作被轉向procfs。這意味著操作vnode的系統調用(比如lookuppn())實際上最終轉向procfs-savvy系統調用(比如prlookup())。

    ◆ /proc能告訴我什么

    Solaris下使用/proc的工具相當完善,位于/usr/proc/bin目錄中。這些工具提供了一種訪問任意指定進程臨界數據的簡捷辦法。比如,想知道一個進程已經打開了多少文件,你可以使用crash(1M)(見鬼,我不會),但是你是root嗎?不必擔心,可以用/usr/proc/bin/pfiles獲取這種信息,圖B演示了pfiles(1)命令的使用:

    --------------------------------------------------------------------------

    [scz@ /export/home/scz]> ps
    PID TTY TIME CMD
    637 pts/3 0:00 bash
    [scz@ /export/home/scz]> pfiles 637
    637: -bash
    Current rlimit: 64 file descriptors
    0: S_IFCHR mode:0620 dev:151,0 ino:196787 uid:500 gid:7 rdev:24,3
    O_RDWR
    1: S_IFCHR mode:0620 dev:151,0 ino:196787 uid:500 gid:7 rdev:24,3
    O_RDWR
    2: S_IFCHR mode:0620 dev:151,0 ino:196787 uid:500 gid:7 rdev:24,3
    O_RDWR
    3: S_IFDOOR mode:0444 dev:191,0 ino:1618164880 uid:0 gid:0 size:0
    O_RDONLY|O_LARGEFILE FD_CLOEXEC door to nscd[213]
    63: S_IFCHR mode:0620 dev:151,0 ino:196787 uid:500 gid:7 rdev:24,3
    O_RDWR FD_CLOEXEC
    [scz@ /export/home/scz]>

    圖B: 使用pfiles(1)命令

    --------------------------------------------------------------------------

    正如上面演示的,/usr/proc/bin下的命令使用很簡單,只需要在命令行上指定PID。然而,留心權限許可設置,與所有普通Unix文件一樣,你無權訪問那些權限設置上禁止訪問的指定PID的進程數據。

    花點事件看看proc(1)手冊頁,熟悉其中介紹的命令,你將學會列舉指定進程相關的庫、進程信號設置、進程信任設置,你甚至可以暫停、重啟進程。

    ◆ 編寫/proc工具

    /proc的魅力在于它包含了你可能想知道的關于一個進程的任何信息,你只需要簡單地從中獲取。/usr/include/sys/procfs.h文件中定義了兩個結構,prstatus和prpsinfo,從中可以獲取指定進程的很多信息。下面是個例子,開發者想知道他的應用程序究竟占用了多少內存。簡單!ls /proc就可以知道了。但是,他還想知道更多細節,他需要知道總的映像大小、常駐部分的大小、堆區(heap)大小、棧區(stack)大小。此外,他希望能夠定期跟蹤這些數據信息,類似vmstat(1M)那種方式。如上所述,聽起來象是一個令人生畏的任務。

    譯者: Solaris 2.6開始這兩個結構定義在/usr/include/sys/old_procfs.h文件中

    然而,通過使用/proc文件系統,我們可以使這項編程挑戰變得容易些。我們寫的這個工具稱做memlook,將顯示指定PID對應的內存統計信息。此外,可以在命令行上指定一個時間間隔,以便定期重新檢測內存利用信息。圖C演示了一次簡單的輸出:

    --------------------------------------------------------------------------

    $ memlook 245
    PID IMAGE RSS HEAP STACK
    245 1499136 1044480 24581 8192
    $

    圖C: memlook的輸出舉例

    --------------------------------------------------------------------------

    下面是memlook.c的源代碼

    --------------------------------------------------------------------------
    /*
    * @(#)memlook.c 1.0 10 Nov 1997
    * Robert Owen Thomas
    robt@cymru.com
    * memlook.c -- A process memory utilization reporting tool.
    *
    * gcc -Wall -O3 -o memlook memlook.c
    */
    #pragma ident "@(#)memlook.c 1.0 10 Nov 1997 Robert Owen Thomas
    robt@cymru.com"

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/signal.h>
    #include <sys/syscall.h>
    #include <sys/procfs.h>
    #include <sys/param.h>
    #include <unistd.h>
    #include <fcntl.h>

    int counter = 10;

    int showUsage ( const char * );
    void getInfo ( int, int );

    int main ( int argc, char * argv[] )
    {
    int fd, pid, timeloop = 0;
    char pidpath[BUFSIZ]; /* /usr/include/stdio.h: #define BUFSIZ 1024 */

    switch ( argc )
    {
    case 2:
    break;
    case 3:
    timeloop = atoi( argv[2] );
    break;
    default:
    showUsage( argv[0] );
    break;
    } /* end of switch */
    pid = atoi( argv[1] );
    sprintf( pidpath, "/proc/%-d", pid ); /* -表示向左靠 */
    if ( ( fd = open( pidpath, O_RDONLY ) ) < 0 )
    {
    perror( pidpath );
    exit( 1 );
    }
    if ( 0 < timeloop )
    {
    for ( ; ; )
    {
    getInfo( fd, pid );
    sleep( timeloop );
    }
    }
    getInfo( fd, pid );
    close( fd );
    exit( 0 );
    } /* end of main */

    int showUsage ( const char * progname )
    {
    fprintf( stderr, "%s: usage: %s < PID > [time delay]\n", progname, progname );
    exit( 3 );
    } /* end of showUsage */

    void getInfo ( int fd, int pid )
    {
    prpsinfo_t prp;
    prstatus_t prs;

    if ( ioctl( fd, PIOCPSINFO, &prp ) < 0 )
    {
    perror( "ioctl" );
    exit( 5 );
    }
    if ( ioctl( fd, PIOCSTATUS, &prs ) < 0 )
    {
    perror( "ioctl" );
    exit( 7 );
    }
    if ( counter > 9 )
    {
    fprintf( stdout, "PID\tIMAGE\t\tRSS\t\tHEAP\t\tSTACK\n" );
    counter = 0;
    }
    fprintf( stdout, "%u\t%-9u\t%-9u\t%-15u\t%-15u\n", pid,
    ( unsigned int )prp.pr_bysize, ( unsigned int )prp.pr_byrssize,
    ( unsigned int )prs.pr_brksize, ( unsigned int )prs.pr_stksize );
    counter++;
    } /* end of getInfo */
    --------------------------------------------------------------------------

    譯者: 作者這里利用了ioctl(),而不是直接讀取/proc下文件,這樣做的好處在于即使系統升級后/proc布局改變,內核中相應ioctl cmd支持也隨之改變,對于應用層的開發者,接口一樣,源代碼可平穩移植。事實上從作者前面舉例來看, memlook.c是在Solaris 2.6以前的版本上開發的,但我并未修改就可以直接用在Solaris 2.6上,雖然此時/proc布局已經發生重大變化。

    仔細閱讀prstatus和prpsinfo結構,尋找那些你敢興趣的成員。在未能真正掌握這種技術之前不要針對/proc文件系統使用write()或者ioctl()。針對特定進程胡亂做write()調用,結果未知。

    ◆ 結論

    當痛苦調試程序或者試圖獲取指定進程狀態的時候,/proc文件系統將是你強有力的支持者。通過它可以創建更強大的工具,獲取更多信息。

    轉載:http://www.51tech.net/news_html/1607.htm

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>