`
gstarwd
  • 浏览: 1536681 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Linux信号量semaphore编程实例

阅读更多

本例示范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                         

//--------------------------msgdequeue.h结束-------------------------------------

//--------------------------test.cpp开始-------------------------------------
//主程序文件

#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;                                            
}      

//--------------------------test.cpp结束-------------------------------------

 编译程序:g++ msgdequeue.h test.cpp -lpthread -lrt -o test
    -lpthread链接pthread库。-ltr链接clock_gettime函数相关库。

    编译后生成可执行文件test。输入./test执行程序。

    线程get_thread每隔1000毫秒从队列取元素,线程put_thread将30个元素依次入队。两个线程模拟两条入队和出队的流水线。因我们在 CMessageDequeue<int> qq(5)处定义了队列最多可容纳5个元素,入队线程每入队到队列元素满5个后需阻塞等待出队线程将队列元素出队才能继续。测试时可调整队列可容纳最大元 素个数来观察运行效果。

分享到:
评论

相关推荐

    linux下信号量例程源码.zip

    在这里,我们将深入探讨Linux信号量的概念、工作原理以及它们在驱动开发中的应用。 信号量是Pete Zaitcev提出的概念,它是一个整数值,可以被系统中的多个进程或线程共享。在Linux内核中,有两种类型的信号量:互斥...

    进程同步与互斥:System V 信号量示例代码

    在Linux中,System V 信号量通过`semaphore`结构体实现,包括一个值、一个等待队列和权限信息。使用System V 信号量需要以下几个步骤: 1. **初始化信号量**:使用`semget`函数创建一个新的信号量集或者获取已存在...

    有名信号量示例代码

    总之,有名信号量是Linux系统编程中用于进程同步的重要机制,通过合理的使用,可以有效地避免数据竞争和死锁等问题。了解并熟练掌握有名信号量的使用,对于编写高效、安全的多进程或多线程程序至关重要。通过阅读`...

    linux/unix系统编程手册附录代码

    - `semaphore`: 信号量,另一种同步机制。 - `pipe()` 和 `fork()` 实现的管道通信。 6. **错误处理和调试**: - `perror()`, `strerror()`: 输出和转换错误消息。 - `assert()`: 断言检查,用于调试代码。 7....

    linux字符设备驱动实例

    可以使用内核提供的锁机制,如自旋锁(spinlock)、信号量(semaphore)等。 9. **调试与日志**:Linux内核提供了一套强大的调试工具,如`printk()`函数用于打印日志,`debugfs`用于创建调试文件,帮助开发者追踪和...

    Linux高级编程部分代码

    3. **信号量(Semaphore)**:信号量是一种用于控制多个进程或线程访问共享资源的同步机制,分为互斥量(二进制信号量)和计数信号量。`sem_t`结构体和`sem_open()`, `sem_wait()`, `sem_post()`等函数是Linux中实现...

    进程通信之信号量.zip

    这个文件很可能是实现或演示信号量的一个实例。通常,它会包含以下关键部分: - 信号量初始化:使用`pthread_semaphore_init`或`semget`创建一个新的信号量。 - P操作:在访问共享资源前调用`pthread_semaphore_...

    linux下的多线程实例--生产者消费者

    3. **信号量(semaphore)**:一种常用的同步机制,用于控制对共享资源的访问。在本例中,信号量被用来控制生产者和消费者之间的数据交换。 4. **命名管道(fifo)**:一种进程间通信(IPC)方式,允许不同进程之间通过...

    Linux高性能服务器编程源码.zip

    Linux提供互斥锁(Mutex)、信号量(Semaphore)、条件变量(Condition Variable)等工具,开发者需要根据场景选择合适的同步机制。 八、性能监控与调优 服务器运行过程中,需要监控CPU、内存、磁盘I/O、网络带宽等...

    linux 一个简单队列实例

    Linux提供了多种同步原语,如信号量(semaphore)、互斥锁(mutex)、条件变量(condition variable)等。例如,可以使用互斥锁保护队列,确保同一时间只有一个线程或进程可以执行入队或出队操作。 六、编程实践 在...

    操作系统_生产者/消费者问题

    操作系统中的生产者/消费者问题是多线程编程中的一个经典示例,它展示了如何通过同步机制来协调并发...文件“信号量Win32”和“信号量Pthread”很可能是分别演示了在两个平台上如何用C或C++代码实现这一问题的实例。

    Linux下的C编程

    常用的同步机制有互斥锁(mutex)、信号量(semaphore)等。 #### 四、网络编程 **4.1 Socket编程** Socket编程是网络通信的基础,它允许程序通过网络发送和接收数据。在Linux中,使用socket库函数可以方便地实现...

    linux进程编程介绍

    Linux提供了多种IPC机制,如管道(Pipe)、命名管道(FIFO)、信号量(Semaphore)、消息队列(Message Queue)、共享内存(Shared Memory)和套接字(Socket)。这些机制允许进程之间交换数据,协同工作。 线程...

    Linux程序设计(包含线程 进程 网路编程)

    Linux支持多种同步原语,如互斥锁(mutex)、条件变量(condition variable)、信号量(semaphore)和读写锁(read-write lock)。这些工具确保了对共享资源的安全访问,防止数据不一致。 在网络编程方面,Linux...

    多核编程实例

    通常需要使用互斥量(Mutex)、信号量(Semaphore)等机制来保护共享资源。 ### 总结 本文档通过几个具体的C/C++示例代码,详细介绍了多核编程中的线程创建、线程管理以及线程同步等基本概念和技术。通过学习这些...

    linux系统编程源代码

    这份源代码是基于Linux操作系统,由尚德机构的课程内容整理而来,提供了实践操作的实例,对于学习和研究Linux内核及系统编程有着极高的价值。 1. **进程管理**:在Linux中,进程是程序的一次执行过程。源代码可能...

    Linux 多线程服务端编程 使用muduo C++ 网络库

    - **信号量(Semaphore)**: 用于控制对有限资源的访问数量。 #### 5. 进程间通信(IPC) - **管道(Pipe)**: 提供了父子进程之间的一种简单通信机制。 - **消息队列(Message Queue)**: 允许不同进程之间发送消息,支持...

    Linux高性能服务器编程

    线程间的同步和互斥(mutex、semaphore、condition_variable)防止数据竞争,信号量和消息队列用于进程间通信。另外,协程和事件驱动编程(如libevent、libev、libuv)可以进一步提升并发性能。 4. **内存管理**:...

    成都大学计算机学院Linux程序设计课程中的实例程序

    在这些实例中,可以看到如何创建子进程(fork)、进程间通信(pipe、socket、信号量、消息队列等)、进程同步与互斥(mutex、semaphore)以及进程调度策略的实现。这些知识点对于理解多线程、多进程编程和并发执行的...

Global site tag (gtag.js) - Google Analytics