真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

信號量(semaphore)-創(chuàng)新互聯(lián)

進程間通信-信號量

創(chuàng)新互聯(lián)專注于彭陽網站建設服務及定制,我們擁有豐富的企業(yè)做網站經驗。 熱誠為您提供彭陽營銷型網站建設,彭陽網站制作、彭陽網頁設計、彭陽網站官網定制、微信平臺小程序開發(fā)服務,打造彭陽網絡公司原創(chuàng)品牌,更為您提供彭陽網站排名全網營銷落地服務。

1、為什么要使用信號量

為了防止多個程序同時訪問一個共享資源而引發(fā)的一系列問題,故有這樣一種方法,在任何一個時刻只有一個執(zhí)行線程訪問代碼的臨界區(qū)(臨界區(qū)是指訪問臨界資源的代碼),而信號量就可以提供這樣的訪問機制,同一時刻只允許一個線程訪問臨界區(qū),也就是說信號量是用來協(xié)調進程共享資源訪問的,也就是說信號量用來協(xié)調進程對共享資源訪問的,其中共享內存就是用信號量實現(xiàn)的。

2、信號量的工作原理

由于信號量只能進行兩種操作等待和發(fā)送信號,他們是p(sv)操作,v(sv)操作。

p(sv)操作:如果sv的值大于0.他就減1,如果sv的值等于0,它就掛起進程的執(zhí)行。

v(sv)操作:如果有其他進程因等待sv而掛起,則就讓他恢復運行,如果沒有進程因等待它而掛起,就讓他加1.

舉個例子,就是 兩個進程共享信號量sv,一旦其中一個進程執(zhí)行了P(sv)操作,它將得到信號量,并可以進入臨界區(qū),使sv減1。而第二個進程將被阻止進入臨界區(qū),因為 當它試圖執(zhí)行P(sv)時,sv為0,它會被掛起以等待第一個進程離開臨界區(qū)域并執(zhí)行V(sv)釋放信號量,這時第二個進程就可以恢復執(zhí)行。

3、Linux信號量機制

Linux提供了一組精心設置的信號量接口來對信號量進行操作。這些函數(shù)都是用來對組的信號量進行操作,他們被聲明在sys/sem.h中。

4、信號量的使用

(1)創(chuàng)建信號量

semget函數(shù)創(chuàng)建一個信號量集或者訪問一個已存在的信號量集

int semget (key_t key, int nsem, int oflag)

返回值是一個稱為信號量標識符的整數(shù),semop和semctl函數(shù)將使用它。成功返回信號量的標示符,失敗返回-1

key:由ftok()函數(shù)得到,

nsem:創(chuàng)建信號量中的個數(shù)

oflag:

    IPC_CREAT:若內核中不存在鍵值與key相等的信號量集,則創(chuàng)建,否則,返回此信號量集的標識符

  IPC_EXCL:單獨使用無意義

  IPC_CREAT | IPC_EXCL :創(chuàng)建一個新的信號量集并返回信號量集的標識符,否則,返回-1.

(2)打開信號量(完成對信號量的PV操作)

用semget打開一個信號量后,對其中一個或多個信號量操作就是用semop來執(zhí)行。

int semop (int semid, struct sembuf * opsptr, size_t nops)

    semid:信號量集標識符

  nsops:進行操作信號量的個數(shù),即sops結構變量的個數(shù),需大于或等于1.

    opspt:是一個指針,它指向一個信號量操作數(shù)組,信號量操作由sembuf結構表示

struct sembuf{
 short sem_num; // 除非使用一組信號量,否則它為0 
 short sem_op; // 信號量在一次操作中需要改變的數(shù)據,通常是兩個數(shù),
 // 一個是-1,即P(等待)操作,一個是+1,即V(發(fā)送信號)操作 
 short sem_flg; // 通常為SEM_UNDO,使操作系統(tǒng)跟蹤信號,并在進程沒有釋放該信號量而終止時,
 // 操作系統(tǒng)釋放信號量 
};

 當操作信號量(semop)時,flg可以設置SEM_UNDO標識;SEM_UNDO用于將修改的信號量值在進程正常退出(調用exit退出或main執(zhí)行完)或異常退出(如段異常、除0異常、收到KILL信號等)時歸還給信號量。進程以SEM_UNDO方式操作后;在進程未退出時,可以改變信號量的值,在進程退出時,將修改的值歸還給信號量,信號量變成原來的值。

(3)在指定信號集或者信號集上的某個信號進行操作

int semctl(int semid,int semnum,int cmd,union semun arg)

    semid: 信號量集標識符

 semnum:信號量集數(shù)組上的下標,表示某一個信號量

第四個參數(shù)是可選的,取決于第個信號(操作對象)

參數(shù)cmd指定以下10種命令中的一種,在semid指定的信號量集合上執(zhí)行此命令。

IPC_STAT  讀取一個信號量集的數(shù)據結構semid_ds,并將其存儲在semun中的buf參數(shù)中。

IPC_SET   設置信號量集的數(shù)據結構semid_ds中的元素ipc_perm,其值取自semun中的buf參數(shù)。

IPC_RMID  將信號量集從內存中刪除。

GETALL    用于讀取信號量集中的所有信號量的值。

GETNCNT  返回正在等待資源的進程數(shù)目。

GETPID    返回最后一個執(zhí)行semop操作的進程的PID。

GETVAL    返回信號量集中的一個單個的信號量的值。

GETZCNT  返回這在等待完全空閑的資源的進程數(shù)目。

SETALL    設置信號量集中的所有的信號量的值。

SETVAL    設置信號量集中的一個單獨的信號量的值。

5.例子

comm.h

#define _PATH_NAME_ "/tmp"
#define _PROJ_ID_ 0x6666

int create_sem_set();

union semun
{
    int val;
    struct semid_ds* buf;
    unsigned short *array;
    struct eminfo*_buf;
};

int init_sem_set(int sem_id,int which,int val);
int create_sem_set(int nums);
int get_sem_set();

int destory_sem_set(int sem_id);

int P(int sem_id,int num);

int    V(int sem_id,int num);

comm.c

#include"comm.h"
static int comm_sem_set(int nums,int flags)
{
    key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
    if(_key<0)
    {
        perror("ftok");
        return -1;
    }
//    int sem_id = semget(_key,nums,IPC_CREAT |IPC_EXCL);
    int sem_id = semget(_key,nums,flags);
    if(sem_id <0)
    {
        perror("semget");
        return -2;
    }
    return sem_id;
}

int create_sem_set(int nums)
{
    int flags = IPC_CREAT | IPC_EXCL | 0666;
    return comm_sem_set(nums,flags);   
}

int get_sem_set()
{    
    int flags = IPC_CREAT;
    return comm_sem_set(0,flags);
}

int destory_sem_set(int sem_id)
{
    if(semctl(sem_id,0,IPC_RMID)<0)
    {
        perror("semctl");
    }
    return 0;
}

int init_sem_set(int sem_id,int which,int val)
{
    union semun _un;
    _un.val = val;
    if(semctl(sem_id,which,SETVAL,_un)<0)
    {
        perror("semctl");
        return -1;
    }
}
static int comm_op(int sem_id,int num,int op)
{
    struct sembuf _sembuf;
    _sembuf.sem_num = num;
    _sembuf.sem_op = op;
    _sembuf.sem_flg = 0;

    if(semop(sem_id,&_sembuf,1)<0)
    {
        perror("semop");
        return -1;
    }
    return 0;
}

int P(int sem_id,int num)
{    
    int op = -1;
    return comm_op(sem_id,num,op);
}

int    V(int sem_id,int num)
{
    int op = -1;
    return comm_op(sem_id,num,op);
}

test_sem.c

#include
#include
#include
#include

#define _PATH_NAME_ "/tmp"
#define _PROJ_ID_ 0x6666

int create_sem_set();

union semun
{
    int val;
    struct semid_ds* buf;
    unsigned short *array;
    struct eminfo*_buf;
};

int init_sem_set(int sem_id,int which,int val);
int create_sem_set(int nums);
int get_sem_set();

int destory_sem_set(int sem_id);

int P(int sem_id,int num);

int    V(int sem_id,int num);
[lh@localhost SEM]$ ^C
[lh@localhost SEM]$ cat comm.c
#include"comm.h"

static int comm_sem_set(int nums,int flags)
{
    key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);

    if(_key<0)
    {
        perror("ftok");
        return -1;
    }
//    int sem_id = semget(_key,nums,IPC_CREAT |IPC_EXCL);
    int sem_id = semget(_key,nums,flags);
    if(sem_id <0)
    {
        perror("semget");
        return -2;
    }
    return sem_id;
}

int create_sem_set(int nums)
{
    int flags = IPC_CREAT | IPC_EXCL | 0666;
    return comm_sem_set(nums,flags);
    
}

int get_sem_set()
{
    
    int flags = IPC_CREAT;
    return comm_sem_set(0,flags);
}

int destory_sem_set(int sem_id)
{
    if(semctl(sem_id,0,IPC_RMID)<0)
    {
        perror("semctl");
    }
    return 0;
}

int init_sem_set(int sem_id,int which,int val)
{
    union semun _un;
    _un.val = val;
    if(semctl(sem_id,which,SETVAL,_un)<0)
    {
        perror("semctl");
        return -1;
    }
}
static int comm_op(int sem_id,int num,int op)
{
    struct sembuf _sembuf;
    _sembuf.sem_num = num;
    _sembuf.sem_op = op;
    _sembuf.sem_flg = 0;

    if(semop(sem_id,&_sembuf,1)<0)
    {
        perror("semop");
        return -1;
    }
    return 0;
}

int P(int sem_id,int num)
{    
    int op = -1;
    return comm_op(sem_id,num,op);
}

int    V(int sem_id,int num)
{
    int op = -1;
    return comm_op(sem_id,num,op);
}
[lh@localhost SEM]$ ^C
[lh@localhost SEM]$ clear

[lh@localhost SEM]$ cat test_sem.c
#include"comm.h"
#include
int main()
{
    int sem_id = create_sem_set(1);
    pid_t id = fork();
    init_sem_set(sem_id,0,1);

    if(id ==0)
    {
        int sem_id_child = get_sem_set();
        while(1)
        {
            P(sem_id_child,0);
            printf("A");
            fflush(stdout);
            usleep(rand()%3);
            printf("A");
            fflush(stdout);
            usleep(rand()%12345);
            V(sem_id_child,0);
        }
    }
    else
    {
        while(1)
        {
            P(sem_id,0);
            printf("B");
            fflush(stdout);
            usleep(rand()%3);
            printf("B");
            fflush(stdout);
            usleep(rand()%12234);
            V(sem_id,0);
        }
        wait(NULL);
        destory_sem_set(sem_id);
    }

    return 0;    
}

信號量(semaphore)

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。


文章題目:信號量(semaphore)-創(chuàng)新互聯(lián)
分享URL:http://weahome.cn/article/dchehd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部