linux设备节点侦测——基于NETLINK

本文介绍了一种设备检测通知机制的实现,通过创建DeviceDetectNotifier和DeviceDetecter接口,实现了设备插入和移除的监听功能。使用Linux内核的Netlink进行事件监听,当设备状态改变时,通知注册的监听器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接口:

class DeviceDetectNotifier
{
public:
    virtual int DeviceEvent(int event, char* dev_name) = 0;
    virtual ~DeviceDetectNotifier() {};
};

class DeviceDetecter
{
public:
    static DeviceDetecter* getInstence();
    virtual int RegisterNotifier(char* deviceName, DeviceDetectNotifier* notifier) = 0;
    virtual ~DeviceDetecter(){};
};

测试代码:

bool run = 1;
bool devExist=0;
pthread_mutex_t     mDeviceMutex;
pthread_cond_t      mDeviceCond;
char aoaName[64] = {0};
char aoaPath[64] = {0};

class AOADeviceDetectNotifier:public DeviceDetectNotifier
{
public:
    virtual int DeviceEvent(int event, char* dev_name)
	{
        pthread_mutex_lock(&mDeviceMutex);
        if(event)
        {
            devExist = true;
            memcpy(aoaName,dev_name,strlen(dev_name));
            pthread_cond_signal(&mDeviceCond);
        }
        else
        {
            memcpy(aoaName,dev_name,strlen(dev_name));
            devExist = false;
        }
        pthread_mutex_unlock(&mDeviceMutex );
		printf("DeviceEvent :%d  aoaName:%s \n",event,aoaName);
	};
    void* dataRevCbk(void* pData,int len);
   ~AOADeviceDetectNotifier(){}
};


int perDetectDevice(char* dev)
{
    int ret = 0;
    if(access(dev,F_OK)==0)
    {
        printf("%s is exist!\n",dev);
        ret = 1;
    }
    return ret;
}


void* devDetectThread(void* parm)
{
    while(run)
    {
        pthread_mutex_lock(&mDeviceMutex);
        if(!devExist)
        {
            pthread_cond_wait(&mDeviceCond, &mDeviceMutex);
        }
        pthread_mutex_unlock(&mDeviceMutex );
        
    if(strlen(aoaPath)<=0)
    {
        sprintf(aoaPath,"%s%s","/dev/",aoaName);
    }
    char* testStr = "hello.";
    char readbuf[100]={0};
    int error = 0;
    
    int fd = open(aoaPath,O_RDWR);
    if(fd<0)
    {
    	printf("AOARWThread open :%s failed.\n",aoaName);
        return NULL;
    }
        
    }
}

int main(int argc, char* argv[])
{
    AOADeviceDetectNotifier aoaNotifier;
    AOADeviceDetectNotifier eapNotifier;
    
    DeviceDetecter* p =DeviceDetecter::getInstence();
    p->RegisterNotifier("aoa",&aoaNotifier);

    char* dev = "/dev/aoa-skel0";
    if(perDetectDevice(dev))
    {
        devExist=1;
        sprintf(aoaPath,"%s",dev);
    }
    pthread_t tid;
    pthread_create(&tid, NULL, devDetectThread, NULL);
    pthread_join(tid, NULL);
    
    //p->RegisterNotifier("usbmisc",&usbmiscNotifier);
    
}

实现:

class DeviceDetecterImpl: public DeviceDetecter
{
public:
    static DeviceDetecterImpl* getInstence();
    virtual int RegisterNotifier(char* deviceName, DeviceDetectNotifier* notifier);
    DeviceDetecterImpl();
    virtual ~DeviceDetecterImpl();

private:
    void DetectThread();
    void startDecodeThread();
    void stopDecodeThread();
    
    static void* detectThread(void* param);
    std::map<char*, DeviceDetectNotifier*> notifierMap;
    //std::thread detectThread;
    bool detectThreadRun;

    pthread_t mThread;
    pthread_mutex_t     mDetectMutex;
    pthread_cond_t      mDetectCond;
};

static std::mutex mtx;
static DeviceDetecterImpl* gDeviceDetecterImpl;
DeviceDetecter* DeviceDetecter::getInstence()
{
    return  DeviceDetecterImpl::getInstence();
}

DeviceDetecterImpl* DeviceDetecterImpl::getInstence()
{
    if (NULL == gDeviceDetecterImpl)
    {
        mtx.lock();
        if (NULL == gDeviceDetecterImpl)
        {
            gDeviceDetecterImpl = new DeviceDetecterImpl();
        }
        mtx.unlock();
    }

    return gDeviceDetecterImpl;
}

void DeviceDetecterImpl::DetectThread()
{
    struct sockaddr_nl client;
    struct timeval tv;
    int CppLive, rcvlen, ret;
    fd_set fds;
    int buffersize = 1024;
    CppLive = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
    memset(&client, 0, sizeof(client));
    client.nl_family = AF_NETLINK;
    client.nl_pid = getpid();
    client.nl_groups = 1; /* receive broadcast message*/
    setsockopt(CppLive, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
    bind(CppLive, (struct sockaddr*)&client, sizeof(client));
    char buf[UEVENT_BUFFER_SIZE] = { 0 };
    
    while (detectThreadRun)
    {
        if(notifierMap.empty())
        {
            usleep(10*1000);
        }
        
        FD_ZERO(&fds);
        FD_SET(CppLive, &fds);
        tv.tv_sec = 0;
        tv.tv_usec = 100 * 1000;
        ret = select(CppLive + 1, &fds, NULL, NULL, &tv);
        if (ret < 0)
            continue;
        if (!(ret > 0 && FD_ISSET(CppLive, &fds)))
            continue;
        /* receive data */
        rcvlen = recv(CppLive, &buf, sizeof(buf), 0);
        if (rcvlen > 0)
        {
            if (!strncmp(buf, "add", 3))
            {
                map<char*, DeviceDetectNotifier*>::iterator iter; 
                for(iter = notifierMap.begin(); iter != notifierMap.end(); iter++)  
                {
                    char* pAoa = strstr(buf, iter->first);
                    if (pAoa != NULL)
                    {
                        DeviceDetectNotifier* p = iter->second;
                        p->DeviceEvent(1,pAoa);
                    }
                } 
            }
            else if (!strncmp(buf, "rem", 3))
            {
                map<char*, DeviceDetectNotifier*>::iterator iter; 
                for(iter = notifierMap.begin(); iter != notifierMap.end(); iter++)  
                {
                    char* pAoa = strstr(buf, iter->first);
                    if (pAoa != NULL)
                    {
                        DeviceDetectNotifier* p = iter->second;
                        p->DeviceEvent(0,pAoa);
                    }
                }
            }
        }
    }
    close(CppLive);
    return;

}

DeviceDetecterImpl::DeviceDetecterImpl()
{
    detectThreadRun = true;
    startDecodeThread();
//    detectThread = std::thread(&DeviceDetecterImpl::DetectThread,gDeviceDetecterImpl);
//    detectThread.detach();
}

void* DeviceDetecterImpl::detectThread(void* param)
{
    DeviceDetecterImpl* pThis = static_cast<DeviceDetecterImpl*>(param);
    if (NULL != pThis)
    {
        pThis->DetectThread();
    }
    else
    {
        printf(" there is no object for MicRecordThread!\n");
    }
}

void DeviceDetecterImpl::startDecodeThread()
{
    int result = pthread_create(&mThread, NULL, detectThread, (void*)this);
    if (result != 0)
    {
        printf("Create pthread error!\n");
    }
}

void DeviceDetecterImpl::stopDecodeThread()
{
    detectThreadRun = false;
    int ret = pthread_join(mThread, NULL);
    printf("pthread_join ret:%d \n", ret);
}
DeviceDetecterImpl::~DeviceDetecterImpl()
{
    stopDecodeThread();
    //detectThread.join();
}

int DeviceDetecterImpl::RegisterNotifier(char* deviceName, DeviceDetectNotifier* notifier)
{
    notifierMap.insert(std::pair<char*, DeviceDetectNotifier*>(deviceName, notifier));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值