前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Linux c 循环检测U盘插拔状态

Linux c 循环检测U盘插拔状态

原创
作者头像
tankaro
发布2025-01-14 09:21:21
发布2025-01-14 09:21:21
830
举报
文章被收录于专栏:Linux 应用程序专栏

前面使用udev机制实现了U盘插拔状态检测,甚至后面与epoll机制结合,满足一些领域的需求,尤其是近似中断机制实现。

但是也有自己的局限性,首先,udev机制与usbip机制无法共存,其次,中断机制在网络传输中不如循环机制,最后在嵌入式开发中,udev检测所有U盘插拔状态有点冗余,单纯scan某个usb的设备节点,效率更高。

下面是一个通过scan特定usb设备节点方式检测U盘插拔检测,这里使用数组检测比直接指定数组下标来检测灵活一些。

main.c

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>


#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#include "scan_udisk.h"
#define MAX_UDISK_ACTIONACTION_SIZE		(16)
#define MAX_UDISK_BUSIDBUSID_SIZE		(16)

typedef enum
{
    SCAN_UDISK_MODE_NONE = -1,
    SCAN_UDISK_MODE_ADD,
    SCAN_UDISK_MODE_REMOVE,
    SCAN_UDISK_MODE_MAX
} SCAN_UDISK_MODE_ST;

int main(int argc, char *argv[])
{
    char usbip_action[MAX_UDISK_ACTIONACTION_SIZE] = "";
    char usbip_busid[MAX_UDISK_BUSIDBUSID_SIZE] = "";
    int while_sleep_second = 1;
    int ret = 1;
    int run_cnt = 1;
    int udisk_scan_mode = SCAN_UDISK_MODE_NONE;

    printf("[%s +%d %s] \n", __FILE__, __LINE__, __func__);

    while(1)
    {

        memset(usbip_action, '\0', MAX_UDISK_ACTIONACTION_SIZE);
        memset(usbip_busid, '\0', MAX_UDISK_BUSIDBUSID_SIZE);

        printf("[%s +%d %s] run_cnt=%d\n", __FILE__, __LINE__, __func__, run_cnt++);
        ret = scan_udisk_mode(usbip_action, usbip_busid);
        if(1 == ret)
        {
            if(SCAN_UDISK_MODE_ADD == udisk_scan_mode)
            {
                printf("[%s +%d %s] scan udisk add twice:usbip_action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, usbip_action, usbip_busid);

            }
            else
            {
                udisk_scan_mode = SCAN_UDISK_MODE_ADD;
                printf("[%s +%d %s] scan udisk add successful:usbip_action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, usbip_action, usbip_busid);
            }
        }
        else if(2 == ret)
        {
            if(SCAN_UDISK_MODE_REMOVE == udisk_scan_mode)
            {
                printf("[%s +%d %s] scan udisk remove twice:usbip_action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, usbip_action, usbip_busid);

            }
            else
            {
                udisk_scan_mode = SCAN_UDISK_MODE_REMOVE;
                printf("[%s +%d %s] scan udisk remove successful:usbip_action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, usbip_action, usbip_busid);
            }
        }
        else
        {
            printf("[%s +%d %s] can not scan udisk mode then continute scan\n", __FILE__, __LINE__, __func__);
        }


        sleep(while_sleep_second);
    }
    return 0;
}

scan_udisk.c

代码语言:txt
复制
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

#include "scan_udisk.h"

#define MAIN_VERSION                0
#define MINIOR_VERSION              1
#define REVISION_VERSION            1
#define CONSTRUCTION_VERSION        1
#define VERSION_STR(s)              #s
#define SC_VERSION(a, b, c, d)     ("loop scan udisk " VERSION_STR(a) "." VERSION_STR(b) "." VERSION_STR(c) "." VERSION_STR(d))
const char g_libVersion[] = SC_VERSION(MAIN_VERSION, MINIOR_VERSION, REVISION_VERSION, CONSTRUCTION_VERSION);

#define ELF_NUM_VERSION        		((MAIN_VERSION<<24) | (MINIOR_VERSION<<16) | (REVISION_VERSION<<8) | (CONSTRUCTION_VERSION<<0))

int get_elf_num_version(void)
{
    //printf("[%s +%d %s] ELF_NUM_VERSION=0x%x\n", __FILE__, __LINE__, __func__, ELF_NUM_VERSION);
    return ELF_NUM_VERSION;
}
char *get_elf_str_version(void)
{
    //printf("[%s +%d %s] (char *)g_libVersion=%s\n", __FILE__, __LINE__, __func__, (char *)g_libVersion);
    return (char *)g_libVersion;
}
#define MAX_SYSTEM_CMD_STR_SIZE	    (64)
#define MAX_UDISK_NAMES_NUM 	    (32)
#define MAX_UDISK_NAMES_SIZE		(16)
#define DEFAULT_UDISK_CNT           (4)
int g_udisk_plug_flag = 0;

char udisk_add_name[MAX_UDISK_NAMES_SIZE];
char dt450_action_busid_dir[] = "/sys/devices/pci0000:00/0000:00:14.0/usb2";
char g_udisk_names[MAX_UDISK_NAMES_NUM][MAX_UDISK_NAMES_SIZE] = {};
char g_default_udisk_names[MAX_UDISK_NAMES_NUM][MAX_UDISK_NAMES_SIZE] = {
    "ep_00",
    "power",
    "2-8",
    "2-7"
};

int check_name_in_array(char *name, int default_cnt)
{
    int j = 0;
    for(j = 0; j < default_cnt; j++)
    {
        //printf("[%s +%d %s] name=%s g_default_udisk_names[j=%d]=%s\n", __FILE__, __LINE__, __func__, name, j, g_default_udisk_names[j]);
        if(0 == strcmp(name, g_default_udisk_names[j]))
        {
            //printf("[%s +%d %s] g_default_udisk_names[j=%d]=%s\n", __FILE__, __LINE__, __func__, j, g_default_udisk_names[j]);
            break;
        }
    }
    //printf("[%s +%d %s] j=%d default_cnt=%d\n", __FILE__, __LINE__, __func__, j, default_cnt);
    if(j == default_cnt)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}
int get_names_from_array(int default_cnt, int get_cnt)
{
    int i = 0;
    int flag = 0;
    //printf("[%s +%d %s] default_cnt=%d get_cnt=%d\n", __FILE__, __LINE__, __func__, default_cnt, get_cnt);
    for(i = 0; i < get_cnt; i++)
    {
        if(0 != check_name_in_array(g_udisk_names[i], default_cnt))
        {
            flag = 1;
            break;
        }
    }
    if(1 == flag)
    {
        //printf("[%s +%d %s] i=%d\n", __FILE__, __LINE__, __func__, i);
        return i;
    }
    return -1;
}
static int get_dir_filenames(char *dir_fullname)
{
    DIR *dir = opendir(dir_fullname);
    if (dir == NULL) {
        perror("opendir");
        return 0;
    }
 
    struct dirent *entry;
    int count = 0;
    //printf("[%s +%d %s] count=%d DEFAULT_UDISK_CNT=%d\n", __FILE__, __LINE__, __func__, count, DEFAULT_UDISK_CNT);
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            //printf("[%d] entry->d_name[%d]=%s g_udisk_plug_flag=%d\n", __LINE__, count, entry->d_name, g_udisk_plug_flag);
            if((MAX_UDISK_NAMES_NUM > count) && (2 < strlen(entry->d_name)) && (6 > strlen(entry->d_name)))
            {
                //printf("[%d] entry->d_name[%d]=%s g_udisk_plug_flag=%d\n", __LINE__, count, entry->d_name, g_udisk_plug_flag);
                strcpy(g_udisk_names[count], entry->d_name);
                count++;
            }
            if(MAX_UDISK_NAMES_NUM <= count)
            {
                printf("[%d] MAX_UDISK_NAMES_NUM(%d) <= count(%d)\n", __LINE__, MAX_UDISK_NAMES_NUM, count);
            }
        }
    }
    //printf("[%s +%d %s] count=%d DEFAULT_UDISK_CNT=%d\n", __FILE__, __LINE__, __func__, count, DEFAULT_UDISK_CNT);
    closedir(dir);
    return count;
}
int scan_udisk_mode(char *action, char *busid)
{
    int count = 0;
    //printf("[%s +%d %s] scan_udisk_mode action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, action, busid);
    count = get_dir_filenames(dt450_action_busid_dir);
    //printf("[%s +%d %s] DEFAULT_UDISK_CNT=%d count=%d\n", __FILE__, __LINE__, __func__, DEFAULT_UDISK_CNT, count);
    if((DEFAULT_UDISK_CNT + 1) == count)
    {
        //printf("[%s +%d %s] scan_udisk_mode udisk_add_name=%s g_udisk_plug_flag=%d\n", __FILE__, __LINE__, __func__, udisk_add_name, g_udisk_plug_flag);
        count = get_names_from_array(DEFAULT_UDISK_CNT, count);
        if(-1 == count)
        {
            return 0;
        }
        strcpy(action, "add");
        strcpy(busid, g_udisk_names[count]);
        strcpy(udisk_add_name, g_udisk_names[count]);            
        g_udisk_plug_flag = 1;
        //printf("[%s +%d %s] add action=%s usbip_busid=%s\n", __FILE__, __LINE__, __func__, action, busid);
        //printf("[%s +%d %s] add udisk_add_name=%s g_udisk_plug_flag=%d\n", __FILE__, __LINE__, __func__, udisk_add_name, g_udisk_plug_flag);
        return 1;
    }
    //printf("[%s +%d %s] scan_udisk_mode udisk_add_name=%s g_udisk_plug_flag=%d\n", __FILE__, __LINE__, __func__, udisk_add_name, g_udisk_plug_flag);

    if(DEFAULT_UDISK_CNT != get_dir_filenames(dt450_action_busid_dir))
    {
        printf("[%s +%d %s] scan_udisk_mode udisk_add_name=%s g_udisk_plug_flag=%d\n", __FILE__, __LINE__, __func__, udisk_add_name, g_udisk_plug_flag);
        return 0;
    }
    if((0 != strlen(udisk_add_name)) && (1 == g_udisk_plug_flag))
    {
        strcpy(action, "remove");
        strcpy(busid, udisk_add_name);       
        g_udisk_plug_flag = 0;
        //printf("[%s +%d %s] remove udisk_add_name=%s g_udisk_plug_flag=%d\n", __FILE__, __LINE__, __func__, udisk_add_name, g_udisk_plug_flag);
        return 2;
    }    
    return 0;
}

scan_udisk.h

代码语言:txt
复制
#pragma once
#include <unistd.h>

#ifdef __cplusplus
extern "C" {
#endif

int get_elf_num_version(void);
char *get_elf_str_version(void);
int scan_udisk_mode(char *action, char *busid);

#ifdef __cplusplus
}
#endif

Makefile

代码语言:txt
复制

# 设置编译器
CC := gcc

#CFLAGS = -Wall -g -O3 -DUSED_FFMPEG -std=c++11 -lpthread -lavcodec -lavutil -lavformat -lswscale -lshallowcompress -L. -I.
#CFLAGS = -Wall -g -O3 -std=c++11 -lpthread -lavcodec -lavutil -lavformat -lswscale -lcompress_transmit -L. -I.
CFLAGS = -Wall -g -O0 -lpthread -L. -I.
# 设置生成的目标文件
current_dir_name := $(notdir $(shell pwd))
TARGET := $(current_dir_name).elf

# 获取所有的.c文件
SRCS := $(wildcard *.c)

# 获取所有的.h文件
DEPS := $(wildcard *.h)

# 将.c文件编译成.o文件
OBJS := $(SRCS:.c=.o)

# 编译规则
$(TARGET): $(OBJS)
	$(CC) -o $@ $(OBJS) $(CFLAGS)
# 依赖规则
%.o: %.c $(DEPS)
	$(CC) -c $< -o $@ $(CFLAGS)

# 清理规则
clean:
	rm -f $(TARGET) $(OBJS)

build.sh

代码语言:txt
复制
#!/bin/bash

currentDir=${PWD}
echo "currentDir=" ${currentDir}

current_basedir=$(basename $currentDir)
echo "rm =" ${current_basedir}

ELFNAME=".elf"
ELFNAME=${current_basedir}${ELFNAME}
echo "ELFNAME=" ${ELFNAME}

if [ -e ${ELFNAME} ]; then
    rm ${ELFNAME}
fi

make clean;make

#./${ELFNAME}
#./$ELFNAME 1 inputParameterFIle.txt 0
#sudo ./$ELFNAME 192.168.70.54 172.17.5.55 0
sudo ./$ELFNAME 192.168.70.54 192.168.70.64 0

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档