溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量

發(fā)布時(shí)間:2021-11-08 11:23:33 來(lái)源:億速云 閱讀:167 作者:小新 欄目:系統(tǒng)運(yùn)維

這篇文章主要為大家展示了“并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量”這篇文章吧。

1 Linux下的互斥信號(hào)量的使用

1)Linux下互斥信號(hào)量的作用

互斥信號(hào)量主要是用于訪問(wèn)共享資源時(shí)保證操作的原子性,即為一個(gè)整體的動(dòng)作不允許被打斷。

2)Linux下的文件操作函數(shù)的學(xué)習(xí)方式

man命令學(xué)習(xí)函數(shù)使用,寫一個(gè)小代碼,將函數(shù)用起來(lái)。

下面就帶大家學(xué)習(xí)下互斥信號(hào)量相關(guān)的函數(shù),然后用代碼將這些函數(shù)串聯(lián)起來(lái),并用并行腳本進(jìn)行一下驗(yàn)證。

2 Linux下互斥信號(hào)量相關(guān)的函數(shù)

1)ftok函數(shù)

ftok函數(shù)用于構(gòu)造鍵值。

① 函數(shù)原型。

key_t ftok( char * fname, int id )

② 頭文件。

include <sys/types.h>    include <sys/ipc.h>

③ 參數(shù)。

fname:文件名在內(nèi)核中的一種數(shù)字表示。

id:項(xiàng)目id號(hào)。

鍵值有fname和項(xiàng)目id號(hào)組合產(chǎn)生。

④ 返回值。

成功:返回產(chǎn)生的鍵值。

失敗:-1。

2)semget函數(shù)

semget函數(shù)用于創(chuàng)建打開(kāi)信號(hào)量。

① 函數(shù)原型。

int semget(key_t key,int nsems,int semflg)

獲取信號(hào)量集合的標(biāo)示符。

當(dāng)key所指定的信號(hào)量不存在的時(shí)候,并且semflg里包含了IPC_CREAT,這個(gè)時(shí)候,就會(huì)創(chuàng)建一個(gè)信號(hào)量集。

② 頭文件。

include <sys/types.h>    include <sys/ipc.h>   include <sys/sem.h>

③ 參數(shù)。

key:鍵值。

semflay:標(biāo)志,可以去IPC_CREAT,對(duì)應(yīng)鍵值的信號(hào)量如果不存在還可以創(chuàng)建信號(hào)量。

nsems:創(chuàng)建的這個(gè)信號(hào)量集合里面包含的信號(hào)量數(shù)目。

④ 返回值。

成功:返回信號(hào)量集合的標(biāo)示符。

失?。?1。

3)semctl函數(shù)

semctl函數(shù)在一個(gè)信號(hào)量集或集合中的單個(gè)信號(hào)量上執(zhí)行各種控制操作。

① 函數(shù)原型。

int semctl(int semid, int semnum, int cmd,.../* union semun arg*/)

② 頭文件。

include <sys/types.h>    include <sys/ipc.h>

③ 參數(shù)。

semid:要控制的信號(hào)量集合的標(biāo)示符。

semnum:用于標(biāo)識(shí)集合中的具體信號(hào)量。

cmd:指定了需執(zhí)行的操作。

信號(hào)量參數(shù)枚舉如下:

union semun {       int   val;                 // SETVAL的值      struct semid_ds *buf;      // IPC_STAT, IPC_SET的緩沖      unsigned short  *array;    // GETALL, SETALL的數(shù)值      struct seminfo  *__buf;    // IPC_INFO的緩沖  };

信號(hào)量集合結(jié)構(gòu)體如下:

struct semid_ds {      struct ipc_perm sem_perm;   // 權(quán)限      time_t          sem_otime;  // 上次semop的時(shí)間     time_t          sem_ctime;  // 上次修改的時(shí)間     unsigned long   sem_nsems;  // 信號(hào)量集中信號(hào)量個(gè)數(shù) };

參數(shù)說(shuō)明如下。

<1 常規(guī)控制操作.

加入下面參數(shù)進(jìn)行操作都會(huì)忽略semnum參數(shù)。

IPC_RMID:立即刪除信號(hào)量集及其關(guān)聯(lián)的semid_ds數(shù)據(jù)結(jié)構(gòu)。

IPC_STAT:在arg.buf指向的緩沖器中放置一份與這個(gè)信號(hào)量集相關(guān)聯(lián)的semid_ds數(shù)據(jù)結(jié)構(gòu)的副本。

IPC SET:使用arg.buf指向的緩沖器中的值來(lái)更新與這個(gè)信號(hào)量集相關(guān)聯(lián)的semid_ds數(shù)據(jù)結(jié)構(gòu)中選中的字段。

<2 獲取和初始化信號(hào)量值。

下面的操作可以獲取或初始化一個(gè)集合中的單個(gè)或所有信號(hào)量的值。獲取一個(gè)信號(hào)量的值需具備在信號(hào)量上的讀權(quán)限,而初始化該值則需要寫權(quán)限。

GETVAL:semctl返回由semid指定的信號(hào)量集中第semmum個(gè)信號(hào)量的值。這個(gè)操作無(wú)需arg參數(shù)。

SETVAL:將由semid指定的信號(hào)量集中第semnum個(gè)信號(hào)量的值初始化arg.val。

GETALL:獲取由semid指向的信號(hào)量集中所有信號(hào)量的值并將它們放arg.array指向的數(shù)組中。

SETALL:使用arg.array指向的數(shù)組中的值初始化semid指向的集合中的所有信號(hào)量。這個(gè)操作將忽略semnum參數(shù)。

注意GETVAL和GETALL返回的信息在調(diào)用進(jìn)程使用它們時(shí)可能已經(jīng)過(guò)期了。

<3 獲取單個(gè)信號(hào)量的信息。

下面的操作返回semid引用的集合中第semnum個(gè)信號(hào)量的信息。所有這些操作都需要在信號(hào)量集合中具備讀權(quán)限,并且無(wú)需arg參數(shù)。

GETPID:返回上一個(gè)在該信號(hào)量上執(zhí)行semopO的進(jìn)程的進(jìn)程ID,這個(gè)值被稱為sempid值。如果還沒(méi)有進(jìn)程在該信號(hào)量上執(zhí)行過(guò)semopO,那么就返回0。

GETNCNT:返回當(dāng)前等待該信號(hào)量的值增長(zhǎng)的進(jìn)程數(shù),這個(gè)值被稱為semncnt值。

GETZCNT:返回當(dāng)前等待該信號(hào)量的值變成0的進(jìn)程數(shù);這個(gè)值被稱為semzcnt值。

與上面介紹的GETVAL和GETALL操作一樣,GETPID、GETNCNT以及GETZCNT操作返回的信息在調(diào)用進(jìn)程使用它們時(shí)可能已經(jīng)過(guò)期了。

④ 返回值。

成功:semctl返回的值取決于cmd,如下。

GETVAL:semval的值。

GETPID:sempid的值。

GETNCNT:semncnt的值。

GETZCNT:semzcnt的值。

其他參數(shù):返回0。

否則,semctl返回-1,并設(shè)置errno以指示錯(cuò)誤。

4)semop函數(shù)

semop函數(shù)用于操作信號(hào)量集合中的信號(hào)量。

① 函數(shù)原型。

int semop(int semid, struct sembuf *sops, unsigned nsops)

② 頭文件。

include <sys/types.h>    include <sys/ipc.h>   include <sys/sem.h>

③ 參數(shù)。

semid:要操作的信號(hào)量集合的標(biāo)示符。

nsops:要操作多少個(gè)信號(hào)量。

sops:對(duì)信號(hào)量執(zhí)行什么樣的操作,執(zhí)行什么操作由struct sembuf這一結(jié)構(gòu)中量決定。

struct sembuf{        unsigned short sem_num;      // 信號(hào)量的數(shù)量       short sem_op;                // 要執(zhí)行的操作       short semf1g;                // 操作標(biāo)志(IPC_NOMAIT和SEM_UNDO) }

當(dāng)sem_op > 0時(shí),將信號(hào)量的值加上sem_op的值。

其結(jié)果是:其他等待減小信號(hào)量值的進(jìn)程可能會(huì)被喚醒并執(zhí)行它們的操作。(需要寫權(quán)限)

當(dāng)sem_op < 0時(shí),將信號(hào)量的值減去sem_op的值。

如果信號(hào)量的當(dāng)前值大于或等于sem_op的絕對(duì)值,那么操作會(huì)立即結(jié)束。否則semop會(huì)阻塞直到信號(hào)量值增長(zhǎng)到在執(zhí)行操作之后不會(huì)導(dǎo)致出現(xiàn)負(fù)值的情況為止。(需要寫權(quán)限)

當(dāng)sem_op =  0時(shí),就對(duì)信號(hào)量值進(jìn)行檢查以確定它當(dāng)前是否等于0。如果等于0,那么操作將立即結(jié)束,否則semop就會(huì)阻塞直到信號(hào)量值變成0為止。(需要讀權(quán)限)

④ 返回值。

成功:0。

失敗:-1。

3 實(shí)例代碼

下面用一個(gè)小程序用一下上面介紹的幾個(gè)函數(shù)。

1)程序原理

首先,通過(guò)并行腳本同時(shí)運(yùn)行程序,在不加入互斥信號(hào)量的時(shí)候,不應(yīng)該被分開(kāi)的程序會(huì)被打斷(插入)。

接著,加入互斥信號(hào)量,此時(shí)并行程序每個(gè)程序都不會(huì)被另一個(gè)程序打斷(插入)。

2)未加入信號(hào)量的情況

下面的頭文件有些是不必要的,加入信號(hào)量需要全部的這些,為了省事,就不去了。

① unsem1.c。

#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h>  void main() {       printf("\nThis is unsem1 start!\n");      sleep(1);  //打印完一條消息間隔會(huì)有      printf("\nThis is unsem1 end!\n");      }

② unsem2.c。

#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h>  void main() {     printf("\nThis is unsem2!\n");   }

③ 3個(gè)腳本文件。

### 腳本run.sh #!/bin/bash ./run1.sh&./run2.sh  ### 腳本文件&mdash;&mdash;run1.sh #!/bin/bash ./unsem1  ### 腳本文件&mdash;&mdash;run2.sh #!/bin/bash ./unsem2

并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量

即腳本run.sh運(yùn)行run1.sh和run2.sh,&可以進(jìn)行程序的并行運(yùn)行。

腳本run1.sh運(yùn)行unsem1.c編譯處理的unsem1。

腳本run2.sh運(yùn)行unsem2.c編譯處理的unsem2。

運(yùn)行結(jié)果如下:

并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量

因?yàn)槭遣⑿羞\(yùn)行,所以兩個(gè)程序不一定誰(shuí)先運(yùn)行,當(dāng)unsem2先運(yùn)行不影響unsem1,但當(dāng)unsem1先運(yùn)行時(shí),unsem2的打印會(huì)插入到unsem1的兩個(gè)打印中間。

程序中用sleep就是為了給插入的機(jī)會(huì)。

3)加入信號(hào)量的情況

下面的文件與上面的文件放到了不同的文件夾下,所以腳本名稱是一樣的并不影響。

① sem1.c。

#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>  #include <sys/ipc.h>  #include <sys/types.h>  #include <sys/sem.h> #include <stdio.h>  #define KEY 1234  union semun {       int val;     // 信號(hào)量的值       struct semid_ds *buf;       unsigned short *arrry; };  void main() {        key_t key;       int semid;       struct sembuf sop;       int ret;             // 創(chuàng)建鍵值       //  key = ftok("./",1);                          //在當(dāng)前目錄可以創(chuàng)建出多個(gè)鍵值,此方法沒(méi)用到            //創(chuàng)建信號(hào)量       semid = semget((key_t)KEY, 1, 0666 | IPC_CREAT); // 利用鍵值創(chuàng)建一個(gè)信號(hào)量            union semun sem_union;                           // 定義給信號(hào)量賦值的結(jié)構(gòu)并賦值       sem_union.val = 1;        ret = semctl(semid,0,SETVAL,sem_union);          // 信號(hào)量的值設(shè)置為1      //    ret = semctl(semid,0,GETVAL);                    // 獲得信號(hào)量的值,想要感受一下semctl可以放開(kāi)這兩個(gè)注釋 //    printf("ret value  is %d\n",ret);            // 1 獲取信號(hào)量       sop.sem_num = 0;//操作第一個(gè)信號(hào)量,編號(hào)為0       sop.sem_op = -1;//-1為獲取信號(hào)量       semop(semid,&sop,1);//由于定義的是變量,參數(shù)是指針?biāo)匀∑涞刂?nbsp;           // 2 打印起始消息       printf("\nThis is sem1 start!\n");            // 3 間隔一會(huì)       sleep(1);            // 4 打印結(jié)束消息       printf("\nThis is sem1 end!\n");            // 5 釋放信號(hào)量       sop.sem_num = 0;//操作第一個(gè)信號(hào)量,編號(hào)為0       sop.sem_op = 1;//加1為釋放信號(hào)量       semop(semid,&sop,1);//由于定義的是變量,參數(shù)是指針?biāo)匀∑涞刂?nbsp; }

② sem2.c。

#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>  #include <sys/ipc.h>  #include <sys/types.h>  #include <sys/sem.h> #include <stdio.h>  #define KEY 1234  void main() {        key_t key;       int semid;       struct sembuf sop;       int ret;            // 打開(kāi)與sem1相同的信號(hào)量       semid = semget((key_t)KEY, 1, 0666 | IPC_CREAT); // 如果已經(jīng)有這個(gè)信號(hào)量了,就不會(huì)創(chuàng)建,就直接打開(kāi)了                 ret = semctl(semid,0,GETVAL);                    // 獲得信號(hào)量的值       //    printf("ret value  is %d\n",ret);                 //獲取信號(hào)量       sop.sem_num = 0;                                 // 操作第一個(gè)信號(hào)量,編號(hào)為0       sop.sem_op = -1;                                 // -1為獲取信號(hào)量       semop(semid,&sop,1);                             // 由于定義的是變量,參數(shù)是指針?biāo)匀∑涞刂?nbsp;           // 打印sem2的消息       printf("\nThis is sem2!\n");            //釋放信號(hào)量       sop.sem_num = 0;                                 // 操作第一個(gè)信號(hào)量,編號(hào)為0       sop.sem_op = 1;                                  // 加1為釋放信號(hào)量       semop(semid,&sop,1);                             // 由于定義的是變量,參數(shù)是指針?biāo)匀∑涞刂?nbsp;  }

③ 3個(gè)腳本文件。

### 腳本run.sh #!/bin/bash ./run1.sh&./run2.sh  ### 腳本文件&mdash;&mdash;run1.sh #!/bin/bash ./sem1  ### 腳本文件&mdash;&mdash;run2.sh #!/bin/bash ./sem2

運(yùn)行結(jié)果如下:


并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量

可以看到不管是sem1先運(yùn)行還是sem2先運(yùn)行,sem1的兩個(gè)打印都不會(huì)被打斷的。

提示:前面學(xué)了文件的操作,這里將終端打印作為共享的資源了,你也可以用操作同一個(gè)文件的方式去驗(yàn)證信號(hào)量的互斥性哈,去試試吧。

以上是“并行Shell腳本如何驗(yàn)證Linux的互斥信號(hào)量”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI