1. 程式人生 > >程序與系統呼叫、程序間通訊--Head First C讀書筆記

程序與系統呼叫、程序間通訊--Head First C讀書筆記

程序與系統呼叫

程序

程序是儲存器中執行的程式。Windows通過taskmgr檢視,Linux通過ps -ef檢視系統中執行的程序。作業系統用一個數字來標識程序,它叫程序識別符號(process identifier,簡稱PID)。

system()函式

system()函式接收一個字串引數,並把它當成命令執行

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char* now()
{
    time_t t;
    time(&t);
    return asctime(localtime(&t));
}

int
main() { char comment[80]; char cmd[20]; fgets(comment, 80, stdin); /* * int sprintf(char *str, char * format [, argument, ...]); * str為要寫入的字串;format為格式化字串,與printf()函式相同;argument為變數 */ sprintf(cmd, "echo '%s %s' >> reports.log", comment, now()); system(cmd); return
0; }

編譯、執行

[[email protected] process]# gcc system.c -o system
[[email protected] process]# ./system 
hello world
[[email protected] process]# ll
總用量 16
-rw-r--r-- 1 root root   39 1017 13:48 reports.log
-rwxr-xr-x 1 root root 7377 1017 13:48 system
-rw-r--r-- 1 root root  320 1017 13
:48 system.c [[email protected] process]# cat reports.log hello world Mon Oct 17 13:48:43 2016

但這樣書寫,並不安全

[[email protected] process]# ./system 
' && ls / && echo '

bin  boot  cgroup  dev  etc  home  lib  lib64  lost+found  media  misc  mnt  net  opt  proc  root  sbin  selinux  srv  sys  tmp  usr  var

剛剛的例子在程式中注入了一段“列出根目錄內容”的程式碼,它也可以刪除檔案獲啟動病毒

exec()函式

exec()函式,告訴作業系統想執行哪個程式,通過執行其他程式來替換當前程序,在unistd.h標頭檔案中。可以告訴exec()函式要使用哪些命令列引數和環境變數。新程式啟動後PID和老程式一樣,就像兩個程式接力跑,你的程式把程序交給了新程式。

這裡寫圖片描述

這裡寫圖片描述

excele

execle.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main()
{
    /*
     * 最後一個NULL必須
     */
    char *my_env[] = {"JUICE=peach and apple", NULL};
    if (execle("diner_info", "diner_info", "4", NULL, my_env) == -1) {
        /*
         * strerror在string.h中
         * errno是變數定義在errno.h中的全域性變數
         * EPERM=1 不允許操作
         * ENOENT=2 沒有該檔案或目錄
         * ESSCH=3 沒有該程序
         * EMULLET=81 這個值任何系統都不存在
         */
        puts(strerror(errno));
    }
    return 0;
}

diner_info.c

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    printf("Diner: %s\n", argv[1]);
    printf("Juice: %s\n", getenv("JUICE"));
    return 0;
}

編譯、執行

[[email protected] process]# gcc execle.c -o execle
[[email protected] exec]# ./execle 
Diner: 4
Juice: peach and apple

excel

excel.c

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main()
{
    if (execl("/sbin/ifconfig", "/sbin/ifconfig", NULL) == -1) {
        fprintf(stderr, "Cannot run ifconfig: %s", strerror(errno));
    }
    return 0;
}

編譯、執行

[[email protected] process]# gcc excel.c -o excel
[[email protected] process]# ./excel 
docker0   Link encap:Ethernet  HWaddr 00:00:00:00:00:00  
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::a039:4fff:feff:86f0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:147108 errors:0 dropped:0 overruns:0 frame:0
          TX packets:270728 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:84534107 (80.6 MiB)  TX bytes:438248842 (417.9 MiB)

eth1      Link encap:Ethernet  HWaddr 00:0C:29:13:02:E8  
          inet addr:10.254.21.122  Bcast:10.254.21.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe13:2e8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:22515732 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6319744 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4312409200 (4.0 GiB)  TX bytes:7210961606 (6.7 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:2614124 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2614124 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1850652329 (1.7 GiB)  TX bytes:1850652329 (1.7 GiB)


/*
 * 當系統找不到你想執行的程式時,就會把errno變數設定
 * 為ENOENT
 * 如上述程式碼如果沒有寫路徑
 */
[[email protected] exec]# ./execlp 
Cannot run ifconfig: No such file or directory

fork()函式

fork()函式,克隆當前程序,新建副本將從同一行開始執行相同程式,變數和變數中的值完全一樣,只有程序識別符號(PID)和原程序不同。原程序叫父程序,而新建副本叫子程序

fork() + exec()執行子程序
1 第一步用fork()系統呼叫複製當前程序。
1.1 程序需要以某種區分自己是父程序還是子程序,為此fork()函式向子程序返回0,向父程序返回非零值。
2 如果是子程序,就exec()。
2.1 這一刻,有兩個完全相同的程序在執行,它們使用相同的程式碼,但子程序(從fork()接收0的那個)現在需要呼叫exec()執行程式替換自己
3 現在有兩個獨立程序,完全不受干擾。
4 為了讓fork程序變快,作業系統使用“寫時複製”(COPY ON WRITE, COW)

fork.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

void error(char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    /*
     * 會立即終止程式,並把退出狀態置為1
     */
    exit(1);
}

int main(int argc, char *argv[])
{
    char *cmd[] = {"/sbin/ifconfig", "/bin/uname"};
    int i = 0;
    for (i = 0; i < 2; i ++) {
        /*
         * fork()會返回一個整型值:為子程序返回0,為父程序返回一個整數,父程序將接收到子程序的程序識別符號
         * 不同作業系統用不同的整數型別儲存程序ID,有的用short,有的用int,作業系統使用哪種型別,pid_t就設為哪個
         * 如果fork()返回-1,就說明在克隆程序時出了問題
         */
        pid_t pid = fork();
        if (pid == -1) {
            error("Can't fork process");
        }
        if (pid == 0) {
            if (execl(cmd[i], cmd[i], NULL) == -1) {
                error("Can't exec process");
            }
        }
    }
    return 0;
}

編譯、執行

[[email protected] process]# gcc fork.c -o fork
[[email protected] process]# ./fork 
[[email protected] process]# docker0   Link encap:Ethernet  HWaddr 00:00:00:00:00:00  
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::a039:4fff:feff:86f0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:147108 errors:0 dropped:0 overruns:0 frame:0
          TX packets:270728 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:84534107 (80.6 MiB)  TX bytes:438248842 (417.9 MiB)

eth1      Link encap:Ethernet  HWaddr 00:0C:29:13:02:E8  
          inet addr:10.254.21.122  Bcast:10.254.21.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe13:2e8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:22521008 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6319910 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4312922254 (4.0 GiB)  TX bytes:7210997918 (6.7 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:2614124 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2614124 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1850652329 (1.7 GiB)  TX bytes:1850652329 (1.7 GiB)

Linux

可以看出,ifconfig和uname兩個命令都執行了;如果去掉fork()函式的話,就只會執行ifconfig命令,因為exec()函式通過執行新程式來替換當前程式,原來的程式就立刻終止了。

小結

這裡寫圖片描述

程序間通訊

檔案描述符

程序內部一瞥,程序用檔案描述符表示資料流,所謂的描述符其實就是一個數字。程序會把檔案描述符和對應的資料流儲存在描述符表中。檔案描述符描述的不一定是檔案。建立程序後,標準輸入連線到鍵盤,標準輸出和標準錯誤連線到螢幕。它們會保持這樣的連線,直到人們把它們重定向到了其他地方。描述表從0到255號。

檔案描述符 資料流 含義
0 鍵盤 標準輸入
1 螢幕 標準輸出
2 螢幕 標準錯誤
#include <stdio.h>

int main()
{
    fprintf(stderr, "this is a error message\n");
    printf("this is a right message\n");
    return 0;
}

編譯、執行

[[email protected] process]# gcc err.c -o err
[[email protected] process]# ./err 
this is a error message
this is a right message

程式執行,便把標準輸出和標準錯誤都輸出到螢幕了

/*
 * 2> 表示“重定向”標準錯誤
 * &1 表示“到標準輸出”
 */
[[email protected] process]# ./err > 1.txt 2>&1
[[email protected] process]# cat 1.txt 
this is a error message
this is a right message

上例表明>重定向了標準輸出和標準錯誤到檔案。

fileno()函式和dup2()函式

這裡寫圖片描述

fileno.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

void error(char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(1);
}

int main()
{
    FILE *file = fopen("stores.txt", "w");
    if (!file)
        error("Can't open the file");

    /*
     * 把向標準輸出流指向了stores.txt文字中
     * 當程式用fopen開啟stores.txt檔案時,作業系統把檔案file註冊到檔案描述符表中
     * fileno(file)是檔案描述符編號,而dup2函式設定了標準輸出符號(1號),讓它也指向了該檔案
     */ 
    if (dup2(fileno(file), 1) == -1)
        error("Can't redirect standard output");
    printf("this is a test message\n");
    return 0;
}

編譯、執行

[root@molaifeng exec]# gcc fileno.c -o fileno 
[root@molaifeng exec]# ./fileno 
[root@molaifeng exec]# cat stores.txt 
this is a test message

使用fileno()函式和dup2()函式改造下fork.c檔案,使其由標準輸出到寫入檔案。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

void error(char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(1);
}

int main(int argc, char *argv[])
{
    char *cmd[] = {"/sbin/ifconfig", "/bin/uname"};
    FILE *file = fopen("stores.txt", "w");
    int i = 0;
    for (i = 0; i < 2; i ++) {
        pid_t pid = fork();
        if (pid == -1) {
            error("Can't fork process");
        }
        if (pid == 0) {
            if (dup2(fileno(file), 1) == -1) {
                error("Can't redirect standard output");
            }
            if (execl(cmd[i], cmd[i], NULL) == -1) {
                error("Can't exec process");
            }
        }
    }
    return 0;
}

編譯、執行

[root@molaifeng exec]# gcc fork.c -o fork
[root@molaifeng exec]# ./fork 
[root@molaifeng exec]# cat stores.txt 
docker0   Link encap:Ethernet  HWaddr 00:00:00:00:00:00  
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::a039:4fff:feff:86f0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:147108 errors:0 dropped:0 overruns:0 frame:0
          TX packets:270096 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:84534107 (80.6 MiB)  TX bytes:438111540 (417.8 MiB)

eth1      Link encap:Ethernet  HWaddr 00:0C:29:13:02:E8  
          inet addr:10.254.21.122  Bcast:10.254.21.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe13:2e8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:21131805 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5967550 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4068910015 (3.7 GiB)  TX bytes:7115255014 (6.6 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:1687125 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1687125 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1278756100 (1.1 GiB)  TX bytes:1278756100 (1.1 GiB)
Linux

waitpid()函式

waitpid()函式會等待子程序結束以後才返回

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    pid_t pid;
    int status, i;
    pid = fork();
    if (pid == 0) {
        printf("This is the child process. pid =%d\n", getpid());
    } else {
        sleep(1);
        printf("This is the parent process, wait for child...\n");
        /*
         * waitpid接收三個引數
         * pid 父程式在克隆子程序時會得到子程序的ID
         * pid_status用來儲存程序退出資訊,因為waitpid需要修改pid_status,因此它不需是個指標
         * 選項,0,函式將等待程序結束【man waitpid】
         */
        if (waitpid(pid, &status, 0) == -1) {
            fprintf(stderr, "this is an error occur when waiting the sub process return");
            exit(1);
        }
        /*
         * 因為pid_status中儲存了好幾條資訊,只有前8位表示程序的退出狀態,可以用巨集來檢視這8位的值
         * 如果退出狀態不是0,變輸出錯誤
         */
        i = WEXITSTATUS(status);
        printf("child's pid =%d . exit status=%d\n", pid, i);
    }
    return 0;
}

編譯、執行

[[email protected] process]# gcc wait.c -o wait
[[email protected] process]# ./wait
This is the child process. pid =41067
This is the parent process, wait for child...
child's pid =41067 . exit status=5

如果把程式碼中的sleep(1)給註釋了,再編譯、執行

[[email protected] process]# gcc wait.c -o wait
[[email protected] process]# ./wait
This is the parent process, wait for child...
This is the child process. pid =41150
child's pid =41150 . exit status=0

pipe()函式

上面學習了用exec()函式和fork()函式執行獨立程序,也知道怎麼把子程序的輸出重定向到檔案,但如何從子程序直接獲取資料呢?在程序執行時實時讀取它生成得資料,而不是等子程序把所有資料都發送到檔案,再從檔案中讀取出來?

答案是有的,可以用管道連線程序。

/*
 * 將描述符放入陣列中
 */
int fd[2];

/*
 * 將陣列名傳給pipe()函式
 * pipe()函式建立了管道,並返回兩個描述符
 * fd[0]用來從管道讀資料
 * fd[1]用來向管道寫資料
 */
if (pipe(fd) == -1) {
    error("Can't create the pipe");
}

這裡寫圖片描述

pipe.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

void error(char *msg)
{
    fprintf(stderr, "%s: %s\n", msg, strerror(errno));
    exit(1);
}

int main()
{
    pid_t pid;
    int status, fd[2];
    char buf[11];
    if (pipe(fd) == -1) {
       error("Can't create the pipe"); 
    }
    pid = fork();
    if (pid == -1) {
        error("Can't fork the process");
    }
    if (pid == 0) {
        dup2(fd[1], 1);
        close(fd[0]);
        sprintf(buf, "%s", "hello world");
        write(fd[1], buf, sizeof(buf));
    }
    dup2(fd[0], 0);
    close(fd[1]);
    read(fd[0], buf, sizeof(buf));
    printf("output: %s\n", buf);
    return 0;
}

編譯、執行

[root@molaifeng process]# gcc pipe.c -o pipe 
[root@molaifeng process]# ./pipe 
output: hello world

訊號

#include <stdio.h>

int main()
{
    char name[30];
    puts("Enter your name:");
    fgets(name, 30, stdin);
    printf("Hello %s\n", name);
    return 0;
}

編譯、執行

[root@molaifeng process]# gcc sig.c -o sig
[root@molaifeng process]# ./sig 
Enter your name:
^C
[root@molaifeng process]#

當執行./sig後,程式正在等待從鍵盤讀取資料,這時按了CTRL+C,程式就停止運行了。為什麼會這樣?程式還沒有執行到第二個printf()就已經退出了,所以CTRL+C停止的不僅僅是fgets(),而是整個程式。是作業系統停止了程式,還是fgets()函式呼叫 了exit()?這中間到底發生了什麼?

奧祕發生在作業系統中,當呼叫fgets()函式時,作業系統會從鍵盤讀取資料,但當看到使用者按了CTRL+C,就會向程式傳送中斷訊號。

訊號是一條簡訊息,即一個整型值。當訊號到來時,程序必須停止手中一切工作去處理訊號。程序會檢視訊號對映表,表中每個訊號都對應一個訊號處理器函式。終端訊號的預設訊號處理器會呼叫exit()函式。

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

/*
 * 新的訊號處理器
 * 作業系統把訊號傳給處理器
 */
void diediedie(int sig)
{
    puts("Goodbye cruel worl ...\n");
    exit(1);
}

/*
 * 註冊處理器的函式
 */
int catch_signal(int sig, void (*handler)(int))
{
    struct sigaction action;
    action.sa_handler = handler;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;
    return sigaction(sig, &action, NULL);
}

int main()
{

    /*
     * SIGINT表示我們要捕捉的中斷訊號
     * 將中斷處理程式設為diediedie()函式
     */
    if (catch_signal(SIGINT, diediedie) == -1) {
        fprintf(stderr, "Can't map the handler\n");
        exit(2);
    }
    char name[30];
    puts("Enter your name:");
    fgets(name, 30, stdin);
    printf("Hello %s\n", name);
    return 0;
}

編譯、執行

[[email protected] process]# ./sig 
Enter your name:
^CGoodbye cruel worl ...

kill 訊號

執行sig程式

[[email protected] process]# ./sig 
Enter your name:
^CGoodbye cruel worl ...

開啟另一個終端,用kill向程式傳送訊號

[root@molaifeng ~]# ps -a
   PID TTY          TIME CMD
 41514 pts/3    00:00:00 sig
 41536 pts/0    00:00:00 ps
[root@molaifeng ~]# kill 41514
[root@molaifeng ~]# kill 41514
-bash: kill: (41514) - 沒有那個程序

以上kill命令將向程序傳送訊號,然後執行程序中配置好的處理函式。但有一個例外,程式碼捕捉不到SIGKILL訊號,也沒法忽略它。也就是說,即使程式有一個錯誤導致程序對任何訊號都視而不見,還是能用kill -KILL結束程序。

[root@molaifeng process]# ./sig 
Enter your name:
已終止

相關推薦

程序系統呼叫程序通訊--Head First C讀書筆記

程序與系統呼叫 程序 程序是儲存器中執行的程式。Windows通過taskmgr檢視,Linux通過ps -ef檢視系統中執行的程序。作業系統用一個數字來標識程序,它叫程序識別符號(process identifier,簡稱PID)。 system()

Head first Java 讀書筆記 -----構造器垃圾收集器

  1.棧與堆 1.記憶體中有兩種區域,物件的生存空間--堆(heap),以及方法呼叫和區域性變數的生存空間--棧(stack)。 2.當你呼叫一個方法時,該方法會放在呼叫棧的棧頂。實際被堆上棧的是堆疊塊,堆疊塊帶有方法的狀態,包括執行到哪一行程式以及所有的區域性變數。

JAVA執行緒執行緒程序程序通訊

I.執行緒與執行緒間通訊 一、基本概念以及執行緒與程序之間的區別聯絡: 關於程序和執行緒,首先從定義上理解就有所不同 1、程序是什麼? 是具有一定獨立功能的程式、它是系統進行資源分配和排程的一個獨立單位,重點在系統排程和單獨的單位,也就是說程序是可以獨 立執行的一段程式。

Linux應用程序基礎 1應用程序系統命令的關系 文件位置 主要用途

soft sock efi 地址欄 -h sha 包安裝 文檔 -a 一、Linux應用程序基礎1、應用程序與系統命令的關系文件位置主要用途使用環境運行格式2、Linxu下軟件包的類型rpmdeb源代碼包自帶安裝程序的軟件包免安裝的軟件包 二、使用RPM包管理工具1、RPM

程序系統呼叫

                            execle()使用  

python 程序執行緒池 非同步呼叫回撥機制

程序池、執行緒池使用案例 程序池與執行緒池使用幾乎相同,只是呼叫模組不同~!! from concurrent.futures import ProcessPoolExecutor # 程序池模組 from concurrent.future

程序通訊之Linux C管道程式設計

管道簡述 管道(pipe)是Unix/Linux中最常見的程序間通訊方式之一,它在兩個程序之間實現一個數據流通的通道,資料以一種資料流的方式在程序間流動。在系統中,管道相當於檔案系統上的一個檔案,用於快取所要傳輸的資料。在某些特性上又不同於檔案,例如當資料讀出後,管道中就沒有資料了,但檔案沒

中斷,異常,系統呼叫程序切換時的堆疊變化和暫存器儲存

 1. 中斷,異常,系統呼叫相同:     CPU自動壓入:   ss            執行級別提升時需切換堆疊,因此多壓入

程序通訊之Linux C命名管道程式設計

命名管道 管道(匿名管道)的使用侷限性大,這與管道的實現機制有關。而命名管道(Named Pipe)不僅可在同一臺計算機的任意不同程序之間通訊,而且還可以在跨越一個網路的不同計算機的不同程序之間,支援可靠的、單向或雙向的資料通訊。 命名管道不同於管道之處在於它提供一個路徑

linux下系統呼叫API系統命令,核心函式的區別聯絡

1.系統呼叫: 應用程式和核心間的橋樑,是應用程式訪問核心的入口點;但通常情況下,應用程式通過作業系統提供的API進行程式設計而不是使用系統呼叫直接程式設計; linux的全部系統呼叫加起來大約只有250個左右。 2.API:   API常以c庫(libc)的形式提供,

指令碼控制------------------------(nicerenice命令程序優先順序控制)

5.4 nice與renice命令 在多工作業系統中,核心負責為系統中執行的每個程序分配CPU時間。實際上,CPU中一次只能執行一個程序,因此核心輪流向每個程序分配CPU時間。 預設情況下,從shell啟動的所有程序在Lin

作業系統系統程式設計(二)程序執行緒

(二)程序與執行緒 1.關於程序: ​ ——程序在使用者方面,包含了程式的執行狀態和這個程式所用的抽象記憶體及儲存資料。 ​ ——程序在作業系統方面:包括: ​ (1)一個程序的執行狀態(通過在程序中儲存”狀態暫存器、指令計數器、棧指標、通用暫存器“等代表程序目

關於系統服務程序共享資料夾管理的幾個方式

2008下可以使用組策略或安全模板來配置實現;2003下用微軟提供的subinacl工具實現,如: subinacl.exe /service * /grant=test=TOP 賦與test使用者啟動、停止、暫停所有服務的權利。 注意,萬用字元“*”有時候不包括一些特殊

Linux程序通訊——IPC共享記憶體學習筆記

一、什麼是共享記憶體 共享記憶體就是允許兩個不相關的程序訪問同一個邏輯記憶體。共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之間共享的記憶體通常安排為同一段實體記憶體。程序可以將同一段共享記憶體連線到它們自己的地址空間中,所有

linux -- 程序的檢視程序id的獲取程序的殺死

程序檢視 ps ax : 顯示當前系統程序的列表  ps aux : 顯示當前系統程序詳細列表以及程序使用者 ps ax|less : 如果輸出過長,可能新增管道命令 less檢視具體程序, 如:ps ax|grep XXX(XXX為程序名稱) 獲取程序id s

基礎IO學習筆記(open等系統呼叫inode檔案理解)

一.系統呼叫介面open、close、write、read 1.open 引數解析: pathname:要開啟或要建立的目標檔案 flags:下面的一個或多個常量進行"或"運算 O_RDONLY

Linux軟中斷系統呼叫

  1. SWI軟中斷 以ARMV7 A/R架構為例, SWI軟中斷和中斷一樣,核心空間處理始於異常向量表。Linux向量表預設地址0XFFFF0000,SWI向量偏移8位元組為0xFFFF0008:     具體程式碼,位於 \linux-3.4.x\arch\a

系統呼叫API之間的關係(圖)

1.為什麼使用者程式不能直接訪問系統核心模式提供的服務?     在linux中,將程式的執行空間分為核心空間與使用者空間(核心態和使用者態),在邏輯上它們之間是相互隔離的,因此使用者程式不能訪問核心資料,也無法使用核心函式。當用戶程序必須訪問核心或使用某個核心函式時,就得使用系統呼叫(System Call

linux -- 程序的檢視程序id的獲取程序的殺死 程序檢視

程序檢視 ps ax : 顯示當前系統程序的列表  ps aux : 顯示當前系統程序詳細列表以及程序使用者 ps ax|less : 如果輸出過長,可能新增管道命令 less檢視具體程序, 如:ps ax|grep XXX(XXX為程序名稱) 獲取程序id shell獲取程序ID的方法:   ps -A

系統呼叫庫函式及兩者的區別

(1)什麼是系統呼叫?      系統呼叫,說的是作業系統提供給使用者程式呼叫的一組“特殊”介面。使用者程式可以通過這組“特殊”介面來獲得作業系統核心提供的服務、比如使用者可以通過檔案系統相關的呼叫請求系統開啟檔案、關閉檔案或讀寫檔案等;從邏輯上來說,系統呼叫可以被看成是一