歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux進程通信——信號量

Linux進程通信——信號量

日期:2017/3/3 11:28:27   编辑:Linux技術
/*
 * 進程間通信之信號量,代碼源自《Linux程序設計》
 */
#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// 使用信號量必須包含該文件
#include <sys/sem.h>

using namespace std;

// 自定義的一個聯合體,信號量相關函數需要使用
union semun
{
    int val;
    struct semid_ds* buf;
    unsigned short* array;
};

// 初始化信號量
int set_semvalue(int semid)
{
    union semun sem_union;
    // 信號量的初始值是1
    sem_union.val = 1;

    // 使用semctl函數去設置它,參數為SETVAL
    if(semctl(semid,0,SETVAL,sem_union) == -1)
    {
        cout << "set_semvalue failed!"<< endl;
        return 0;
    }
    return 1;
}

// 刪除一個信號量
int del_semvalue(int semid)
{
    union semun sem_union;
    // 使用semctl去刪除它,標志是IPC_RMID
    if(semctl(semid,0,IPC_RMID,sem_union) == -1)
    {
        cout << "del_semvalue failed!"<< endl;
        return 0;
    }

    return 1;
}

// 等待信號量
int semaphore_p(int semid)
{
    struct sembuf sem_b;

    sem_b.sem_num = 0;  // 如果不是使用一組信號,那麼這個值一般都是0
    sem_b.sem_op = -1;    // 表示進行P操作
    sem_b.sem_flg = SEM_UNDO; // 默認都要設置為SEM_UNDO(這是為了,當進程異常退出的時候,系統可以釋放進程持有的信號量)
    // 調用semop進行P操作
    if(semop(semid,&sem_b,1) == -1)
    {
         cout << "semaphore_p failed!"<< endl;
        return 0;
    }

    return 1;
}

// V操作,釋放信號量
int semaphore_v(int semid)
{
    struct sembuf sem_b;

    sem_b.sem_num = 0;
    sem_b.sem_op = 1;   // 1表示進行V操作
    sem_b.sem_flg = SEM_UNDO;

    if(semop(semid,&sem_b,1) == -1)
    {
         cout << "semaphore_v failed!"<< endl;
        return 0;
    }
    return 1;
}

int main(int argc,char* argv[])
{
    // 信號量的id
    int sem_id;

    char op_char = 'O';

    // 創建或者打開一個信號量(信號量不存在就創建、存在就打開)
    sem_id = semget((key_t)1234,1,0666|IPC_CREAT);

    // 用一個額外的參數去控制哪個進程對信號量進行初始化,即如果當前進程有額外的參數
    // 那麼它就對信號量進行初始化
    if(argc > 1)
    {
        // 初始化信號量
        if(set_semvalue(sem_id) == 0)
        {
            return -1;
        }

        op_char = 'X';
        sleep(2);
    }

    for(int i = 0; i < 10; ++i)
    {
        // 等待信號量
        if(semaphore_p(sem_id) == 0)
        {
            return -1;
        }

        // 打印一些信息
        cout << op_char ;
        cout.flush();
        sleep(2);
        cout << op_char;
        cout.flush();

        // 釋放信號量,即V操作
        if(semaphore_v(sem_id) == 0)
        {
            return -1;
        }

        sleep(2);
    }

    // 執行結束,打印一些信息
    cout << endl << getpid() << " - finished" << endl;

    // 用額外的參數去控制進程去刪除信號量
    if(argc > 1)
    {
        if(del_semvalue(sem_id) == 0)
        {
            return -1;
        }
    }
    return 0;
}
Copyright © Linux教程網 All Rights Reserved