advanced-linux-programming

[advanced linux programming]

出處: Advanced Linux Programming


更新記錄

item note
20170104 第一版

目錄


man使用方式 (1.5)

  • man手冊頁分成1~9如下
    1 用戶指令
    2 系統調用
    3 標準庫函數
    8 系統/管理員命令

  • The table below shows the section numbers of the manual followed by the types of pages they contain.
    1 Executable programs or shell commands
    2 System calls (functions provided by the kernel)
    3 Library calls (functions within program libraries)
    4 Special files (usually found in /dev)
    5 File formats and conventions eg /etc/passwd
    6 Games
    7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
    8 System administration commands (usually only for root)
    9 Kernel routines [Non standard]

  • man example

    • man sleep

      1
      2
      3
      4
      5
      6
      NAME
      sleep - delay for a specified amount of time

      SYNOPSIS
      sleep NUMBER[SUFFIX]...
      sleep OPTION
    • 查看函數手冊
      man 3 sleep

      1
      2
      3
      4
      5
      6
      7
      NAME
      sleep - sleep for the specified number of seconds

      SYNOPSIS
      #include <unistd.h>

      unsigned int sleep(unsigned int seconds);
    • 查看所有手冊的介紹
      whatis sleep

      1
      2
      sleep (3)            - sleep for the specified number of seconds
      sleep (1) - delay for a specified amount of time
    • 尋找相關的命令
      man -k sleep

      1
      2
      3
      4
      5
      6
      clock_nanosleep (2)  - high-resolution sleep with specifiable clock
      nanosleep (2) - high-resolution sleep
      rtcwake (8) - enter a system sleep state until specified wakeup time
      sleep (1) - delay for a specified amount of time
      sleep (3) - sleep for the specified number of seconds
      usleep (3) - suspend execution for microsecond intervals
  • info提供更完整的說明
    info - read Info documents

    1
    2
    3
    4
    info gcc
    info ld
    info as
    info libc
  • 源碼
    linux原碼放置於/usr/src目錄

    1
    2
    3
    4
    5
    $ ls -l /usr/src
    total 52
    drwxr-xr-x 24 root root 4096 Mar 29 2016 linux-headers-4.2.0-34
    drwxr-xr-x 7 root root 4096 Mar 29 2016 linux-headers-4.2.0-34-generic
    drwxr-xr-x 24 root root 4096 Apr 7 2016 linux-headers-4.2.0-35

查看程式library依賴性 (2.3)

  • 範例使用libtiff開啟TIFF格式圖片
    默認情況下,link會選用共享庫版本的libtiff,通常位於/usr/lib/libtiff.so
    因為libtiff會引用libjpeg和libz

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ cat tifftest.c 
    #include <stdio.h>
    #include <tiffio.h>

    int main(int argc, char **argv)
    {
    TIFF* tiff;
    tiff = TIFFOpen(argv[1], "r");
    TIFFClose(tiff);
    return 0;
    }

    $gcc -o tifftest tifftest.c -ltiff
  • ldd tifftest

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ ldd tifftest
    linux-vdso.so.1 => (0x00007fff1077f000)
    libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007f82b6b72000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f82b67ad000)
    liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f82b658a000)
    libjbig.so.0 => /usr/lib/x86_64-linux-gnu/libjbig.so.0 (0x00007f82b637c000)
    libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f82b6127000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f82b5f0d000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f82b5c07000)
    /lib64/ld-linux-x86-64.so.2 (0x000055ab68d5b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f82b5a03000)
[GCC_CompilationProcess]

圖片出處: GCC and Make Compiling, Linking and Building C/C++ Applications

fork(3-3)

程序建立可使用下例方式
1.system
2.fork和exec

使用system會受限於shell限制,一般為(Bash shell),需查看/bin/sh是連結到才能確認

  • example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     $ cat fork.c 
    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>

    int main()
    {
    pid_t child_pid;

    printf("the main program proceass ID is %d\n",(int) getpid());

    child_pid = fork ();

    if ( child_pid != 0 ){
    printf("this is the parent process,with id %d\n",(int) getpid());
    printf("the child's process ID is %d\n", (int)child_pid);
    }
    else
    {
    printf("this is the child process,with id %d\n", (int) getpid());
    }
    return 0;
    }
  • fork-test

    1
    2
    3
    4
    5
    $ ./fork-test 
    the main program proceass ID is 22729
    this is the parent process,with id 22729
    the child's process ID is 22730
    this is the child process,with id 22730

Linux 下的 fork() 是「non-spawn behavior」,因為他不會去跑一個外部程式,而是「複製 parent process 成為 child process」;那麼,要怎麼做出「spawn behavior」的 fork() 呢

如何使用fork及exec來取代system

fork會生成子程序,跑相同一份程式
需使用exec來跑其它程式

  • example

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    $ cat fork-exec.c 
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>

    int spawn (char* program, char** arg_list)
    {
    pid_t child_pid;
    child_pid = fork();

    if( child_pid != 0){
    //parent
    return child_pid;
    }else{
    //child
    execvp(program,arg_list);
    fprintf(stderr,"an error occurred in execvp\n");
    abort();
    }
    }

    int main(){
    char* arg_list[] = {
    "ls",
    "-l",
    "/",
    NULL
    };

    spawn("ls",arg_list);
    printf("done with main program\n");
    return 0;
    }

    $ ./fork-exec
    done with main program
    total 30844
    drwxr-xr-x 2 root root 4096 Apr 15 2016 bin
    drwxr-xr-x 5 root root 4096 Aug 8 09:07 boot
    drwxrwxr-x 2 root root 4096 Mar 29 2016 cdrom
    drwxr-xr-x 19 root root 4900 Jan 3 10:30 dev
  • execvp

    When execvp() is executed, the program file given by the first argument will be loaded into the caller’s address space and over-write the program there.

  • execv

    the syhstem call execv executes a file,transforming the calling process into a new process.
    after a successful execv, there is no return to the calling process

  • Differences between exec and fork

線程(4-1)

  • 出處: 中文書籍
    线程(thread),不同于进程(process),是一种允许一个程序同时执行不止一个任务的机制
    线程看起来是并行运行的
    Linux 核心对它们进行异步调度,不断中断它们的执行以给,其它线程执行的机会
    GNU/Linux 实现了 POSIX 标准线程 API(所谓 pthreads)

mutex lock

互斥体是一种特殊的锁:同一时刻只有一个线程可以锁定它。
当一个锁被某个线程锁定的时候,如果有另外一个线程尝试锁定这个互斥体,则这第二个线程会被阻塞,或者说被置于等待状态

pthread_mutex_t mutex
pthread_mutex_init (&mutex, NULL);

  • pthread_mutex_lock
    线程可以通过调用 pthread_mutex_lock 尝试锁定一个互斥体
    如果这个互斥体没有被锁定,则这个函数调用会锁定它然后立即返回
    如果这个互斥体已经被另一个线程锁定,则pthread_mutex_lock 会阻塞调用线程的运行

其它參考資料