#include#include#includ" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Arm平臺 Qt檢測U盤插拔(三)-----蛋疼的recv(

系統(tǒng) 2755 0

因為最終要在tiny210上實現(xiàn)此功能,最終選擇了hotplug。

http://hi.baidu.com/hdy5200075/item/7751f48647f3d12a100ef3f6這里是hotplug檢測U盤的源碼,我在qt里將其寫到一個hostplug.h文件里。

    #ifndef HOSTPLUG_H
#define HOSTPLUG_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <errno.h>
#include <fcntl.h>

static int init_hotplug_sock(void)
{
    struct sockaddr_nl snl;
    const int buffersize = 16 * 1024 * 1024;
    int retval;
    memset(&snl, 0x00, sizeof(struct sockaddr_nl));
    snl.nl_family = AF_NETLINK;
    snl.nl_pid = getpid();
    snl.nl_groups = 1;
    int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if(hotplug_sock == -1)
    {
        printf("Error getting socket;%s\n", strerror(errno));
        return -1;
    }

    /*set receive buffersize*/
    setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize));

    
      
        
           int flags=fcntl(hotplug_sock, F_GETFL,0); fcntl(hotplug_sock, F_SETFL, flags | O_NONBLOCK);
        
      
    
    


    retval = bind(hotplug_sock, (struct sockaddr*)&snl, sizeof(struct sockaddr_nl) );
    if(retval < 0)
    {
        printf("bind failed: %s", strerror(errno));
        close(hotplug_sock);
        hotplug_sock = -1;
        return -1;
    }
    return hotplug_sock;
}

#endif // HOSTPLUG_H

  
然后添加一個定時器,定時器時間為500ms,即每500ms掃描一次,如下:

    void Widget::timerEvent(QTimerEvent *event)
{
    static int n = 0;
    char buf[1024] = {0};   //UEVENT_BUFFER_SIZE*2


    if(event->timerId() == timer.timerId())
    {
        recv(hotplug_sock, &buf, sizeof(buf), 0); //use a timer to query socket from core -netlink
        QString result = buf;
         rectFlag = result;
        qDebug()<<result;
        if(result.contains("add"))
        {
            n++;
            if (n>10)
                n = 10;
            ui->progressBar->setValue(n);
        }
        else if(result.contains("remove"))
        {
            n--;
            if(n<0)
                n = 0;
            ui->progressBar->setValue(n);
        }


    }
    else
        QWidget::timerEvent(event);
}
  
注意這里最關(guān)鍵的就是
    recv(hotplug_sock, &buf, sizeof(buf), 0);
  

這個函數(shù),接收消息存至buf里。但默認的hotplug_sock是阻塞的,也就是當執(zhí)行到recv時,程序就會停在這里,直到再次接收到內(nèi)核新的消息,程序才會往下執(zhí)行。為此,程序必須改動,一種思路是開一個線程,專門運行recv,停在那也無所謂;另外一種思路是將這個sock改成非阻塞的,改動部分見.h文件里畫紅線部分!

int flags=fcntl(hotplug_sock, F_GETFL,0);
fcntl(hotplug_sock, F_SETFL, flags | O_NONBLOCK);


當內(nèi)核沒有消息時,recv()之后的buf是空的。 交叉編譯后,程序至Tiny210里運行良好!


上一張效果圖:

Arm平臺 Qt檢測U盤插拔(三)-----蛋疼的recv()阻塞
但遺憾的是,工業(yè)是這么做是很不高明的,為了掃描一個U盤要開一個定時器在那掃描,因此最終采用判斷/proc/scsi/usb-storage是否存在來判斷u盤是否插入。曾考慮過U盤插入后,掛載點/udisk是否存在來判斷。但當用戶在/udisk目錄下時,這時突然拔掉U盤。/udisk就會存在,而且ls查看的結(jié)果是報錯。這時因為未推出U盤目錄就拔掉,linux無法正常卸載造成的。當U盤插入良好時,usb-storage文件夾里會有三個文件,當卸載不成功時,會有兩個文件。當卸載成功時,usb-storage這個文件夾會消失。采用像/udisk里寫測試文件來判斷/udisk是否可用,不可用的話就提示給用戶:

    bool Widget::checkSaveFile()
{

    QString fileName = "/proc/scsi/usb-storage/a.txt";
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly|QFile::Text))
        return false;
    else
    {   file.close();
        file.remove();
        return true;
    }

}
  
查詢U盤狀態(tài)的槽函數(shù):

    void Widget::on_queryButton_clicked()
{
    QDir dir("/proc/scsi/usb-storage"); //在板子上,如果檢測掛載點,改為:QDir dir("/udisk")檢測掛載點
    QMessageBox box;
      QString mess;
    box.setWindowTitle(tc->toUnicode("U盤狀態(tài)"));    
    qDebug()<<"dir.count() = "<<dir.count();

    if(rectFlag.contains("add"))
        mess = tc->toUnicode("正在識別,請稍等-----");
    else if(rectFlag.contains("remove"))
        mess = tc->toUnicode("正在刪除您的U盤-------");
    else if(dir.exists())
    {
        if(dir.count()>2 )
        {
           // if(checkSaveFile())
                mess = tc->toUnicode("U盤已連接!");
           // else
               // mess = tc->toUnicode("您的U盤已插入,但掛載點有問題,不能正常使用!建議拔掉U盤,然后重啟!");

        }
        else if((dir.count() == 2) )
        {
            QDir dirMount("/udisk");
                        if(dirMount.exists())
                        {
                          int fd =  system("umount /udisk");
                        qDebug()<<"fd = "<<fd;
                        }
                        else
                            mess = tc->toUnicode("/udisk No Exist!");

//            if(checkSaveFile())
//                mess = tc->toUnicode("您未插入U盤。但掛載點可寫,不影響使用。如果需要請插入U盤!"); //這種情況從邏輯上講不可能出現(xiàn)。
//            else
//                mess = tc->toUnicode("您未插入U盤。但當前掛載點有問題,建議重啟后再插入U盤!");
        }
        else
            mess = tc->toUnicode("U盤連接有故障,請重啟后再插入U盤!");
    }

    else
        mess = tc->toUnicode("U盤未連接!");
   // process->start("ls /mnt\n");

    //QString test = QString::number(a, 10);
//    QString test = process->readAllStandardOutput();
//    ui->getTextEdit->insertPlainText(test + "\n");

    ui->getTextEdit->insertPlainText(mess + "\n");
    autoScroll();

  
    }
  
這樣就能正常檢測U盤了,如果想加進度條就加上。不加,也能正常檢測。

問題又來了,上面采用向/udisk里寫測試文件來檢測/udisk是否可用,但有時用戶會將U盤進行寫保護。我試遍所有的方法,用open、opendir、access、stat等來檢查異常情況下/udisk的屬性與正常狀態(tài)有何不同,最終也沒查出來。也用了ls /udisk > /a.txt,截取ls的內(nèi)容。但當/udisk出現(xiàn)異常時,報錯的內(nèi)容是板子上報的,并不是ls顯示的內(nèi)容。ls此時顯示結(jié)果為空。

其實,與其判斷這種誤拔U盤的行為,倒不如防止。經(jīng)過我研究發(fā)現(xiàn),當ls出現(xiàn)/udisk fatal error,只要執(zhí)行/umount /udisk,手動將這個文件夾卸載,再次插上U盤就可以了。為此,大家看到我上面程序里,當檢測dir.count == 2時,檢查/udisk是否存在,如果存在則將/udisk卸載。

這樣做基本算完美解決問題了。美中不足的是,當異常出現(xiàn)時,如果板子程序一直在運行,則拔掉U盤再插上無事。如果此時板子重啟,在板子重啟前就將U盤再次插入到板子,這時候因為咱們的應(yīng)用程序還未運行,還沒有執(zhí)行 umount /udisk,這個時候程序就檢測不出來了。

要避免這個問題,就采用往U盤里寫數(shù)據(jù)的方法判斷,或者如果允許掃描用hostplug查詢出來的信息可以得知usb的注冊情況,這種思路應(yīng)該也可以。一個小小的U盤檢測,終于告一段落了,實現(xiàn)了x86下、arm平臺均可用的qt檢測U盤!----------------yanzi1225627

這里給一個源碼資源,是老外寫的,用qtcpsocket來監(jiān)聽netlink的消息,老外寫的代碼就是不一樣啊,大家參考吧:

http://download.csdn.net/detail/yanzi1225627/4514740

Arm平臺 Qt檢測U盤插拔(三)-----蛋疼的recv()阻塞


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 午夜福利国产在线观看1 | 日本福利在线观看 | 五月色电影 | 一级毛片视频在线 | 国产三级在线精品男人的天堂 | 久久r热这里有精品视频 | 精品中文字幕久久久久久 | 手机三级电影 | 国产乱妇无码大黄AA片 | 日韩欧美二区在线观看 | 日本一本免费一二区 | 亚洲精品手机在线 | 涩涩97| 91看片在线 | 偷拍亚洲制服另类无码专区 | 一区二区三区无码高清视频 | 精品不卡 | 亚洲午夜成激人情在线影院 | 九九热国产精品视频 | 狠狠干夜夜撸 | 久久香蕉国产线熟妇人妻 | 又大又紧又硬又湿a视频 | 色播视频在线播放 | 日韩2区| 奇米一区二区 | 亚洲国产精品99久久久久久久久 | 日韩在线小视频 | 中文字幕日韩在线 | 美国一级欧美三级 | 91精品国产色综合久久不卡蜜臀 | 精品伊人网 | 久久视频这里只有精品35 | 日韩欧美不卡在线 | 国产三级在线播放 | 国产精品久久久久久久久久久久 | 久久久无码精品成人A片小说 | 久操精品| 欧美精品一区二区三区在线 | 一本伊大人香蕉久久网手机 | 久久久久无码国产精品一区 | 欧美久久xxxxxx影院 |