`
fujinbing
  • 浏览: 238876 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于sem信号量

阅读更多


msgdequeue.h
本例示范Linux信号量的基本用法。
该范例使用了两个线程分别对一个公用队列进行入队和出队操作,
并用信号量进行控制,当队列空时出队操作可以被阻塞,
当队列满时入队操作可以被阻塞。

    主要用到的信号量函数有:
    sem_init:初始化信号量sem_t,初始化的时候可以指定信号量的初始值,以及是否可以在多进程间共享。

    sem_wait:一直阻塞等待直到信号量>0。

    sem_timedwait:阻塞等待若干时间直到信号量>0。

    sem_post:使信号量加1。

    sem_destroy:释放信号量。和sem_init对应。

    关于各函数的具体参数请用man查看。如man sem_init可查看该函数的帮助。

    下面看具体的代码:

    //--------------------------msgdequeue.h开始-------------------------------------

    //实现可控队列

    #ifndef MSGDEQUEUE_H
    #define MSGDEQUEUE_H

    #include "tmutex.h"
    #include <iostream>
    #include <errno.h>
    #include <time.h>
    #include <semaphore.h>
    #include <deque>

    using namespace std;
    template<typename T,typename MUTEX_TYPE = ThreadMutex>

    class CMessageDequeue

    {

    public:

    CMessageDequeue(size_t MaxSize) : m_MaxSize( MaxSize ){
        sem_init( &m_enques,0, m_MaxSize ); //入队信号量初始化为MaxSize,最多可容纳MaxSize各元素
        sem_init( &m_deques,0,0 ); //队列刚开始为空,出队信号量初始为0

    }

    ~CMessageDequeue(){
    sem_destroy(&m_enques);
    sem_destroy(&m_deques);
    }

    int sem_wait_i( sem_t *psem, int mswait ){
//等待信号量变成>0,mswait为等待时间,若mswait<0则无穷等待,否则等待若干mswait毫秒。

    if( mswait < 0 ){
     int rv = 0;
     while( ((rv = sem_wait(psem) ) != 0 ) && (errno == EINTR ) );    //等待信号量,errno==EINTR屏蔽其他信号事件引起的等待中断
    return rv;
    }else{

    timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts );    //获取当前时间
    ts.tv_sec += (mswait / 1000 );        //加上等待时间的秒数
    ts.tv_nsec += ( mswait % 1000 ) * 1000; //加上等待时间纳秒数
    int rv = 0;
    while( ((rv=sem_timedwait( psem, &ts ))!=0) && (errno == EINTR) );   //等待信号量,errno==EINTR屏蔽其他信号事件引起的等待中断
    return rv;
    }
    }
    bool push_back( const T &item, int mswait = -1 ){
//等待mswait毫秒直到将item插入队列,mswait为-1则一直等待
if( -1 == sem_wait_i( &m_enques, mswait )){

    return false;

    }

    //AUTO_GUARD:定界加锁,见Linux多线程及临界区编程例解的tmutex.h文件定义。

    AUTO_GUARD( g, MUTEX_TYPE, m_lock );

    try{
          m_data.push_back( item );

    cout << "push " << item << endl;

    sem_post( &m_deques );

    return true;

    }catch(){

    return false;

    }

    }

    bool pop_front( T &item, bool bpop = true, int mswait = -1 ){
    //等待mswait毫秒直到从队列取出元素,mswait为-1则一直等待

if( -1 == sem_wait_i( &m_deques, mswait ) ){

    return false;

    }

    //AUTO_GUARD:定界加锁,见Linux多线程及临界区编程例解的tmutex.h文件定义。

    AUTO_GUARD( g, MUTEX_TYPE, m_lock );

    try{

item = m_data.front();

    if( bpop ){

m_data.pop_front();

    cout << "pop " << item << endl;

    }

    sem_post( &m_enques );

    return true;

    }catch(){

    return false;

    }

    }

    inline size_t size(){
return m_data.size();

    }

    private:

    MUTEX_TYPE m_lock;

    deque<T> m_data;

    size_t m_MaxSize;

    sem_t m_enques;

    sem_t m_deques;

    };

#endif



#include "msgdequeue.h"
#include <pthread.h>
#include <iostream>

    using namespace std;
    CMessageDequeue<int> qq(5);
    void *get_thread(void *parg);
    void *put_thread(void *parg);

    void *get_thread(void *parg){

    while(true){

    int a = -1;

    if( !qq.pop_front( a,true, 1000 ) ){
    cout << "pop failed. size=" << qq.size() <<endl;
    }

    }

    return NULL;

    }

    void *put_thread(void *parg){

    for(int i=1; i<=30; i++){
    qq.push_back( i, -1 );
    }
    return NULL;

    }

    int main()

    {
     pthread_t pget,pput;
     pthread_create( &pget,NULL,get_thread,NULL);
     pthread_create( &pput, NULL, put_thread,NULL);
     pthread_join( pget,NULL ); pthread_join( pput,NULL );

    return 0;

    }


tmutex.h

#ifndef TMUTEX_H
#define TMUTEX_H
#include <pthread.h>
//线程互斥量
struct ThreadMutex
{
ThreadMutex()
{
        pthread_mutex_init(&mtx,NULL);
        }

        ~ThreadMutex()
        {
                pthread_mutex_destroy( &mtx );
        }

        inline void lock()
        {
                pthread_mutex_lock( &mtx );
        }

        inline void unlock()
        {
                pthread_mutex_unlock( &mtx );
        }

        pthread_mutex_t mtx;

};                                                           
                                                             
//空互斥量,即调用lock时什么事都不做。                                       
struct NullMutex
{                                                            
        inline void lock()
        {                                                    
        }                                                    
        inline void unlock()
        {                                                    
        }                                                    
};                                                           

template<class T>                                            
class CAutoGuard
{                                                            
public:                                                      
        CAutoGuard(T &mtx) : m_mtx(mtx)
        {                                                    
                m_mtx.lock();                                
        }                                                    
        ~CAutoGuard()
        {                                                    
                m_mtx.unlock();                              
        }                                                    
protected:                                                   
        T &m_mtx;                                            
};                                                           
                                                             
#define AUTO_GUARD( guard_tmp_var, MUTEX_TYPE, mtx )        
        CAutoGuard<MUTEX_TYPE> guard_tmp_var(mtx)            
#endif

分享到:
评论

相关推荐

    Sem.rar_linux sem_linux sem.c_信号量

    本资源“Sem.rar”包含的是一个关于System V信号量的C语言实现,特别适用于Linux环境。System V信号量是一种同步原语,用于解决多进程间的资源访问冲突问题,确保共享数据的安全性。 首先,让我们深入理解什么是...

    c语言信号量的使用实例

    例如,POSIX标准提供了一套信号量API,包括`sem_init()`、`sem_wait()`、`sem_post()`等函数。 #### 三、信号量的实现 在给定的部分内容中,提供了两个示例程序:`sema.c`和`semb.c`,它们共同演示了信号量的使用...

    linux信号量详解

    1. **sem_init(sem_t\* sem, int pshared, unsigned value)**:初始化信号量,参数`sem`指向待初始化的信号量对象,`value`为其初始值,`pshared`指示信号量是否可以在进程间共享。 2. **sem_destroy(sem_t\* sem)*...

    有名信号量示例代码

    在Linux中,有名信号量可以通过`sem_open()`, `sem_post()`, `sem_wait()`, `sem_close()`和`sem_unlink()`等系统调用来操作。 1. **创建有名信号量**: 使用`sem_open()`函数创建有名信号量。该函数需要一个唯一...

    ucosIII信号量多值信号量二值信号量互斥信号量

    ### uC/OS-III信号量详解 #### 一、信号量概述 信号量作为一种重要的同步机制,在嵌入式实时操作系统中发挥着关键作用。它主要用于处理任务间通信及资源的互斥访问问题。uC/OS-III作为一款广泛使用的嵌入式实时...

    sem.rar_信号量_嵌入式系统

    在"sem.rar"这个压缩包中,可能包含的是关于t-engine系统中信号量编程的示例代码或教程。"www.pudn.com.txt"可能是相关资料的来源链接或说明,供进一步学习和参考。通过这些资源,开发者可以深入理解如何在实际项目...

    Vxworks信号量分析

    为了避免这种情况,可以调整信号量属性,如使用`SEM_Q_PRIORITY`,并确保在创建时将信号量设置为满状态(SEM_FULL)。 使用信号量时应注意以下几点: 1. 不同用途的信号量应配置不同的属性和初始值。 2. 在互斥访问...

    sem.tar.gz_linux 信号量_linux 封装

    "sem.tar.gz_linux 信号量_linux 封装"是一个压缩包,它包含了一个已经封装好的信号量接口,便于开发者在自己的程序中方便地使用信号量进行进程间的通信和同步。 信号量的基本概念是源自于荷兰计算机科学家Dijkstra...

    无名信号量示例代码

    无名信号量的创建通常使用`sem_init()`函数,该函数接收三个参数:指向信号量结构体的指针、标志(决定信号量是否是进程间共享)和初始值。例如: ```c #include sem_t sem; sem_init(&sem, 0, 1); // 初始化一个...

    ucos-ii学习笔记——信号量集(事件标志组)的原理及使用

    例如,在上面的代码中,我们创建了一个信号量集`Sem_F`,并将其用于控制三个任务之间的同步。任务`MyTask`只有在任务`YouTask`和`HerTask`都发送了信号以后才能运行。 信号量集的优点 信号量集有一些优点,例如: ...

    Linux之信号量_很全面的分析_个人整理的

    其中,`sem_init()`函数的第一个参数是指向信号量的指针,第二个参数为0表示无名信号量,第三个参数初始化信号量的值。 ##### 2. 有名信号量 有名信号量用于进程间通信,其值保存在文件系统中,因此可以在不同进程...

    sem_syn.rar_linux syn_信号量_线程 同步

    - `sem_init()`: 初始化信号量,传入信号量指针、初始值和是否为共享信号量标志。 - `sem_wait()`: 也称为P操作,减小信号量的值,如果值小于0,则线程被阻塞。 - `sem_post()`: 也称为V操作,增加信号量的值,若...

    2.线程间同步和通信之信号量(静态)

    `rt_sem_init()`函数用于初始化一个静态信号量,它需要三个参数:信号量结构体指针、信号量名称和初始值。例如,我们可以创建一个初始值为1的二进制信号量,这样只有一个线程能获得该信号量并访问资源。 ```c rt_...

    linux信号量机制

    `sem_init()`、`sem_post()`、`sem_wait()`、`sem_trywait()`和`sem_destroy()`是其核心函数,它们共同维护了信号量的创建、修改、检查和销毁,从而确保并发环境下的数据一致性。在实际编程中,信号量是一种强大且...

    信号量的使用

    在实际编程中,我们可以使用系统提供的API来操作信号量,例如在Unix/Linux系统中,可以使用`sem_init()`、`sem_wait()`(P操作)和`sem_post()`(V操作)等函数。 在多线程环境下,信号量常用于控制对共享资源的...

    哈工大软件学院操作系统实验4——信号量的实现和应用

    在这个实验中,学生需要编写`sem.c`文件,这通常是实现信号量操作的核心部分。可能包括对信号量的初始化、P操作和V操作的实现。例如,可以使用互斥锁(mutex)来实现二进制信号量,或者使用条件变量(condition ...

    用有名信号量和匿名信号量实现进程互斥

    在上述代码中,`N_SEM`宏定义了使用哪种类型的信号量,当其值为0时使用匿名信号量,非0则使用有名信号量。 在创建有名信号量时,我们使用`sem_open`函数,提供信号量的路径名`SEM_PATH`和相应的权限。而匿名信号量...

    Linux互斥锁、条件变量和信号量

    2. 计数信号量:可以控制同时访问资源的线程数量,`sem_t`类型也可以表示计数信号量。 信号量的操作函数包括: - 初始化:`sem_init()`用于初始化信号量。 - P操作(获取):`sem_wait()`或`sem_p()`,若信号量值...

    信号量YUV.zip_信号量处理

    在C语言中,信号量通常通过系统调用来实现,如`sem_open`, `sem_post`, `sem_wait`等。`semaphore.c`很可能是这个示例的主要源代码文件,它将演示如何在程序中创建、初始化、增加和减少信号量。`semaphore.h`可能...

Global site tag (gtag.js) - Google Analytics