Ubuntu 1804 Desktop U盘/光驱插入监测及挂载监测
Ubuntu 1804 Desktop U盤/光驅插入監測及掛載監測
最近做的項目要求在不使用第三方庫、不更改系統設置及普通用戶權限情況下,實時監控U盤及CD-ROM的插入及掛載情況,現在把內容整理一下。
一. 主要數據結構介紹
本程序共有2個主要的數據結構:
- Netlink操作隊列
- 設備隊列:新插入設備類型、設備名、掛載目錄隊列
1. Netlink操作隊列
本隊列主要用于存儲NetLink傳來的數據,便于處理進程進行處理,數據結構及相關函數如下:
typedef struct _OperationQueue {char operation[20]; //哪種操作char DeviceName[NAME_MAX]; //設備名struct _OperationQueue *pNext; //下一節點 } OperationQueue;//判斷操作隊列是否為空 bool IsEmpty_OperationQueue(OperationQueue *pOperationQueue) {return ((pOperationQueue->pNext == NULL) ? true : false); }//向隊列中存入數據 int Push_OperationQueue(OperationQueue *pOperationQueue, char *operation, char *DeviceName) {pthread_mutex_lock(&OperationQueueLock);OperationQueue *LastNode = pOperationQueue;int QueueLen = 0;while (LastNode->pNext != NULL){LastNode = LastNode->pNext; //找到尾節點QueueLen++;}if (QueueLen >= MAX_QUEUE_SIZE){printf("Queue is full!\n");pthread_mutex_unlock(&OperationQueueLock);return -1;}LastNode->pNext = (OperationQueue *)malloc(sizeof(OperationQueue));memset(LastNode->pNext, 0, sizeof(OperationQueue));LastNode->pNext->pNext = NULL;strcpy(LastNode->pNext->operation, operation);strcpy(LastNode->pNext->DeviceName, DeviceName);pthread_mutex_unlock(&OperationQueueLock);return 0; }//從隊列中取出數據 bool Pop_OperationQueue(OperationQueue *pOperationQueue, char *operation, char *DeviceName) {pthread_mutex_lock(&OperationQueueLock);if (pOperationQueue->pNext == NULL){printf("Queue is empty!\n");pthread_mutex_unlock(&OperationQueueLock);return false;}strcpy(operation, pOperationQueue->pNext->operation);strcpy(DeviceName, pOperationQueue->pNext->DeviceName);pOperationQueue->pNext = pOperationQueue->pNext->pNext;// printf("%s ------- %s\n", operation, DeviceName);// fflush(stdout);pthread_mutex_unlock(&OperationQueueLock);return true; }2. 設備隊列:新插入設備類型、設備名、掛載目錄隊列
本隊列主要用于存儲處理后最終信息,數據結構及相關函數如下:
typedef struct _DeviceLink {int type; //設備類型 0: udisk; 1: cdromchar DeviceName[PATH_MAX + NAME_MAX]; //設備名char MountPath[PATH_MAX + NAME_MAX]; //掛載路徑struct _DeviceLink *pNext; //下一節點 } DeviceLink;//輸出設備信息 void OutputDeviceLink(DeviceLink *pDeviceLink) {pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;while (CurNode != NULL){printf("--------------------------\n");printf("type: %s\n", ((0 == CurNode->type) ? "udisk" : "cdrom"));printf("DeviceName: %s\n", CurNode->DeviceName);printf("MountPath: %s\n", CurNode->MountPath);fflush(stdout);CurNode = CurNode->pNext;}printf("--------------------------\n\n\n\n");pthread_mutex_unlock(&DeviceLinkLock);return; }//新增設備 void AddDeviceLink(int type, char *DeviceName, char *MountPath, DeviceLink *pDeviceLink) {// printf("-+-+-+-+-+-+-AddDeviceLink-+-+-+-+-+-+-+-\n");// fflush(stdout);pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;DeviceLink *LastNode = pDeviceLink;// 先遍歷一圈,看看有沒有while (CurNode != NULL){if (strcmp(DeviceName, CurNode->DeviceName) == 0){// CurNode->type = type;// // 判斷一下掛載目錄有沒有變化,有變化就更新一下// if ((MountPath[0] != '\0') && (strcmp(MountPath, CurNode->MountPath) != 0))// {// strcpy(MountPath, CurNode->MountPath);// }pthread_mutex_unlock(&DeviceLinkLock);return;}CurNode = CurNode->pNext;}// 沒有就新建一個節點while (LastNode->pNext != NULL){LastNode = LastNode->pNext; //找到尾節點}LastNode->pNext = (DeviceLink *)malloc(sizeof(DeviceLink));memset(LastNode->pNext, 0, sizeof(DeviceLink));LastNode->pNext->pNext = NULL;LastNode->pNext->type = type;// char temp[PATH_MAX + NAME_MAX] = "/dev/";// strcat(temp, DeviceName);// strcpy(LastNode->pNext->DeviceName, temp);strcpy(LastNode->pNext->DeviceName, DeviceName);strcpy(LastNode->pNext->MountPath, MountPath);pthread_mutex_unlock(&DeviceLinkLock);// OutputDeviceLink(pDeviceLink);return; }//更新設備信息 void UpdateDeviceLink(DeviceLink *pDeviceLink, MountMap *pMountMap, int mapnum) {pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurpDeviceLinkNode = pDeviceLink->pNext;// 先遍歷一圈pDeviceLinkwhile (CurpDeviceLinkNode != NULL){bool found = false;for(int i=0; i<mapnum; i++){if (0 == strcmp(CurpDeviceLinkNode->DeviceName, pMountMap[i].DeviceName)) //判斷當前設備是否在掛載列表中{found = true;strcpy(CurpDeviceLinkNode->MountPath, pMountMap[i].MountPath);break;}}if (false == found){strcpy(CurpDeviceLinkNode->MountPath, "");}CurpDeviceLinkNode = CurpDeviceLinkNode->pNext;}pthread_mutex_unlock(&DeviceLinkLock);return; }//刪除設備信息 void DeleteDeviceLink(char *DeviceName, DeviceLink *pDeviceLink) {// printf("-+-+-+-+-+-+-DeleteDeviceLink-+-+-+-+-+-+-+-\n");// printf("Delete %s\n", DeviceName);// fflush(stdout);pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;DeviceLink *PreNode = pDeviceLink;while (CurNode != NULL){if (strcmp(DeviceName, CurNode->DeviceName) == 0){PreNode->pNext = CurNode->pNext;free(CurNode);CurNode = NULL;pthread_mutex_unlock(&DeviceLinkLock);return;}else{PreNode = CurNode;CurNode = CurNode->pNext;}}pthread_mutex_unlock(&DeviceLinkLock);return; }二. 進程介紹
本程序共4個進程:
- USB插入監測進程:從NetLink得到操作及設備名,存入Netlink操作隊列中
- 解析操作數據進程:從Netlink操作隊列中取出數據,處理后存入設備隊列中
- 獲取掛載信息進程:通過循環遍歷系統掛載文件判斷設備隊列中設備掛載情況
- 主進程:休眠并定時打印出新插入的設備是U盤或光驅、打印出U盤/光驅名及掛載情況
1. USB插入監測進程
由于考慮到權限及不更改系統設置情況,udev就無法使用,經過網上檢索,發現了NetLink監測USB插入。
Netlink是linux提供的用于內核和用戶態進程之間的通信方式,這里就不展開介紹,通過socket與內核進行通信,得到USB設備插入、拔出等信息。
在網上找了一些NetLink的代碼demo,進行了簡單修改,直接把應用層接收到的NetLink信息打印出來,代碼如下:
使用gcc編譯,后運行,結果如下:
發現NetLink發送的事件共有以下5種:add、bind、change、remove、unbind,而結合我們的設備名(U盤:sdb,sdb1,光驅:sr0),我們發現只有以下3種可以用到:
- add:插入
- change:更改
- remove:移除
確定操作之后,要截取對應的設備名,將操作和設備名成對存入Netlink操作隊列,截取部分代碼如下所示:
char operation[20] = {0}; strncpy(operation, (char *)nlh, 19); *(strchr(operation, '@')) = '\0';char DeviceName[NAME_MAX] = {0}; strcpy(DeviceName, strrchr((char *)nlh, '/') + 1);// printf("%s ------- %s\n", operation, DeviceName); // fflush(stdout);Push_OperationQueue(pOperationQueue, operation, DeviceName);2. 解析操作數據進程
本進程負責當Netlink操作隊列不為空時,處理Netlink操作隊列中的數據,存入設備隊列中,代碼如下:
void ResolveOperationProcess(void *arg) {OperationQueue *pOperationQueue = ((ResolveOperationProcessParams *)arg)->pOperationQueue;DeviceLink *pDeviceLink = ((ResolveOperationProcessParams *)arg)->pDeviceLink;// printf("-------------ResolveOperationProcess-----------------\n");// printf("pDeviceLink: %x\n", pDeviceLink);// printf("((ResolveOperationProcessParams *)arg)->pDeviceLink: %x\n", ((ResolveOperationProcessParams *)arg)->pDeviceLink);// printf("pOperationQueue: %x\n", pOperationQueue);// printf("((ResolveOperationProcessParams *)arg)->pOperationQueue: %x\n", ((ResolveOperationProcessParams *)arg)->pOperationQueue);// fflush(stdout);printf("ResolveOperationProcess ...\n");char operation[20] = {0};char DeviceName[NAME_MAX] = {0};while (1){if (IsEmpty_OperationQueue(pOperationQueue)){// printf("-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");// fflush(stdout);sleep(2);continue;}// if (!Pop_OperationQueue(pOperationQueue, operation, DeviceName));// {// continue;// }// printf("-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");// fflush(stdout);Pop_OperationQueue(pOperationQueue, operation, DeviceName);// printf("%s ------- %s\n", operation, DeviceName);// fflush(stdout);if (strlen(DeviceName) < 3)continue;if ('s' == DeviceName[0] && 'd' == DeviceName[1] && (DeviceName[2] >= 'a' || DeviceName[2] <= 'z')) //sda~sdz, udisk{if (0 == strcmp(operation, "add")){AddDeviceLink(0, DeviceName, "", pDeviceLink);}else if (0 == strcmp(operation, "remove")){DeleteDeviceLink(DeviceName, pDeviceLink);}else if (0 == strcmp(operation, "change")){AddDeviceLink(0, DeviceName, "", pDeviceLink);}elsecontinue;}else if ('s' == DeviceName[0] && 'r' == DeviceName[1] && (DeviceName[2] >= '0' || DeviceName[2] <= '9')) //sr0~sr9, cdrom{if (0 == strcmp(operation, "add")){AddDeviceLink(1, DeviceName, "", pDeviceLink);}else if (0 == strcmp(operation, "remove")){DeleteDeviceLink(DeviceName, pDeviceLink);}else if (0 == strcmp(operation, "change")){AddDeviceLink(1, DeviceName, "", pDeviceLink);}elsecontinue;}elsecontinue;}return; }3. 獲取掛載信息進程
Ubuntu 18.04 Desktop中設備掛載情況存儲再/proc/mounts文件中,通過遍歷該文件,得到所有掛載對應關系,然后對比設備隊列,更新設備隊列中的掛載路徑。代碼如下:
void CheckMountProcess(DeviceLink *pDeviceLink) {printf("CheckMountProcess ...\n");while (1){// 獲取行數,用于確定創建對照表的大小int row = 0;char cmd[MAX_BUFF_LEN] = {0};char buffer[MAX_BUFF_LEN] = {0};FILE *pf;sprintf(cmd, "cat %s | grep -n \" \" | awk -F \":\" '{print $1}' | tail -n1", FILE_MOUNT_CHECK);// system(cmd);pf = popen(cmd, "r");fread(buffer, sizeof(buffer), 1, pf);row = atoi(buffer);pclose(pf);// printf("ROW: %d\n", row);char RawData[1024] = {0};FILE *fp = fopen(FILE_MOUNT_CHECK, "r");if (NULL == fp){printf("failed to open dos.txt\n");continue;}MountMap *pMountMap = (MountMap *)malloc(sizeof(MountMap) * row);if (NULL == pMountMap){printf("Malloc failed!\n");continue;}memset(pMountMap, 0, sizeof(MountMap) * row);int mapnum = 0; // 對照表實際大小while (!feof(fp)){memset(RawData, 0, sizeof(RawData));fgets(RawData, sizeof(RawData) - 1, fp); // 包含了換行符// printf("%s", RawData);if (strlen(RawData) <= 5)continue;if ((RawData[0] != '/') || (RawData[1] != 'd') || (RawData[2] != 'e') || (RawData[3] != 'v') || (RawData[4] != '/')) // 不是/dev/開頭,直接passcontinue;char DeviceName[PATH_MAX + NAME_MAX] = {0};char MountPath[PATH_MAX + NAME_MAX] = {0};strcpy(DeviceName, RawData + 5); // +5是為了去掉/dev/*strchr(DeviceName, ' ') = '\0';strcpy(MountPath, strchr(RawData, ' ') + 1);*strchr(MountPath, ' ') = '\0';// printf("DeviceName: %s \t MountPath: %s\n", DeviceName, MountPath);strcpy(pMountMap[mapnum].DeviceName, DeviceName);strcpy(pMountMap[mapnum].MountPath, MountPath);mapnum ++;}fclose(fp);UpdateDeviceLink(pDeviceLink, pMountMap, mapnum);free(pMountMap);pMountMap = NULL;sleep(2); //2秒輪詢一次}return; }4. 主進程
每隔5秒鐘,輸出一下設備隊列。代碼如下:
while (1) {sleep(5);OutputDeviceLink(pDeviceLink);// printf("Sleep .........\n");fflush(stdout); }三. 現象展示
執行gcc UsbMonitor.c -o UsbMonitor -lpthread編譯后運行。結果如下:
光驅現象類似,就不具體展示了。
四. 完整代碼
完整代碼如下:
#include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <sys/socket.h> #include <sys/types.h> #include <string.h> #include <pthread.h> #include <asm/types.h> #include <linux/netlink.h> #include <linux/socket.h> #include <linux/limits.h>#define UEVENT_BUFFER_SIZE 2048 /* maximum payload size*/ #define MAX_QUEUE_SIZE 1024 //隊列大小 #define MAX_PAYLOAD 1024 /* maximum payload size*/ #define MAX_BUFF_LEN 128 //命令最大字符數#define FILE_MOUNT_CHECK "/proc/mounts" //用來檢測設備是否被mountstatic pthread_mutex_t DeviceLinkLock; static pthread_mutex_t OperationQueueLock;typedef struct _DeviceLink {int type; //設備類型 0: udisk; 1: cdromchar DeviceName[PATH_MAX + NAME_MAX]; //設備名char MountPath[PATH_MAX + NAME_MAX]; //掛載路徑struct _DeviceLink *pNext; //下一節點 } DeviceLink;typedef struct _OperationQueue {char operation[20]; //哪種操作char DeviceName[NAME_MAX]; //設備名struct _OperationQueue *pNext; //下一節點 } OperationQueue;typedef struct _ResolveOperationProcessParams {DeviceLink *pDeviceLink;OperationQueue *pOperationQueue; } ResolveOperationProcessParams;typedef struct _MountMap {char DeviceName[PATH_MAX + NAME_MAX];char MountPath[PATH_MAX + NAME_MAX]; } MountMap;//判斷操作隊列是否為空 bool IsEmpty_OperationQueue(OperationQueue *pOperationQueue) {return ((pOperationQueue->pNext == NULL) ? true : false); }//向隊列中存入數據 int Push_OperationQueue(OperationQueue *pOperationQueue, char *operation, char *DeviceName) {pthread_mutex_lock(&OperationQueueLock);OperationQueue *LastNode = pOperationQueue;int QueueLen = 0;while (LastNode->pNext != NULL){LastNode = LastNode->pNext; //找到尾節點QueueLen++;}if (QueueLen >= MAX_QUEUE_SIZE){printf("Queue is full!\n");pthread_mutex_unlock(&OperationQueueLock);return -1;}LastNode->pNext = (OperationQueue *)malloc(sizeof(OperationQueue));memset(LastNode->pNext, 0, sizeof(OperationQueue));LastNode->pNext->pNext = NULL;strcpy(LastNode->pNext->operation, operation);strcpy(LastNode->pNext->DeviceName, DeviceName);pthread_mutex_unlock(&OperationQueueLock);return 0; }//從隊列中取出數據 bool Pop_OperationQueue(OperationQueue *pOperationQueue, char *operation, char *DeviceName) {pthread_mutex_lock(&OperationQueueLock);if (pOperationQueue->pNext == NULL){printf("Queue is empty!\n");pthread_mutex_unlock(&OperationQueueLock);return false;}strcpy(operation, pOperationQueue->pNext->operation);strcpy(DeviceName, pOperationQueue->pNext->DeviceName);pOperationQueue->pNext = pOperationQueue->pNext->pNext;// printf("%s ------- %s\n", operation, DeviceName);// fflush(stdout);pthread_mutex_unlock(&OperationQueueLock);return true; }//輸出設備信息 void OutputDeviceLink(DeviceLink *pDeviceLink) {pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;while (CurNode != NULL){printf("--------------------------\n");printf("type: %s\n", ((0 == CurNode->type) ? "udisk" : "cdrom"));printf("DeviceName: %s\n", CurNode->DeviceName);printf("MountPath: %s\n", CurNode->MountPath);fflush(stdout);CurNode = CurNode->pNext;}printf("--------------------------\n\n\n\n");pthread_mutex_unlock(&DeviceLinkLock);return; }//新增設備 void AddDeviceLink(int type, char *DeviceName, char *MountPath, DeviceLink *pDeviceLink) {// printf("-+-+-+-+-+-+-AddDeviceLink-+-+-+-+-+-+-+-\n");// fflush(stdout);pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;DeviceLink *LastNode = pDeviceLink;// 先遍歷一圈,看看有沒有while (CurNode != NULL){if (strcmp(DeviceName, CurNode->DeviceName) == 0){// CurNode->type = type;// // 判斷一下掛載目錄有沒有變化,有變化就更新一下// if ((MountPath[0] != '\0') && (strcmp(MountPath, CurNode->MountPath) != 0))// {// strcpy(MountPath, CurNode->MountPath);// }pthread_mutex_unlock(&DeviceLinkLock);return;}CurNode = CurNode->pNext;}// 沒有就新建一個節點while (LastNode->pNext != NULL){LastNode = LastNode->pNext; //找到尾節點}LastNode->pNext = (DeviceLink *)malloc(sizeof(DeviceLink));memset(LastNode->pNext, 0, sizeof(DeviceLink));LastNode->pNext->pNext = NULL;LastNode->pNext->type = type;// char temp[PATH_MAX + NAME_MAX] = "/dev/";// strcat(temp, DeviceName);// strcpy(LastNode->pNext->DeviceName, temp);strcpy(LastNode->pNext->DeviceName, DeviceName);strcpy(LastNode->pNext->MountPath, MountPath);pthread_mutex_unlock(&DeviceLinkLock);// OutputDeviceLink(pDeviceLink);return; }//更新設備信息 void UpdateDeviceLink(DeviceLink *pDeviceLink, MountMap *pMountMap, int mapnum) {pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurpDeviceLinkNode = pDeviceLink->pNext;// 先遍歷一圈pDeviceLinkwhile (CurpDeviceLinkNode != NULL){bool found = false;for(int i=0; i<mapnum; i++){if (0 == strcmp(CurpDeviceLinkNode->DeviceName, pMountMap[i].DeviceName)) //判斷當前設備是否在掛載列表中{found = true;strcpy(CurpDeviceLinkNode->MountPath, pMountMap[i].MountPath);break;}}if (false == found){strcpy(CurpDeviceLinkNode->MountPath, "");}CurpDeviceLinkNode = CurpDeviceLinkNode->pNext;}pthread_mutex_unlock(&DeviceLinkLock);return; }//刪除設備信息 void DeleteDeviceLink(char *DeviceName, DeviceLink *pDeviceLink) {// printf("-+-+-+-+-+-+-DeleteDeviceLink-+-+-+-+-+-+-+-\n");// printf("Delete %s\n", DeviceName);// fflush(stdout);pthread_mutex_lock(&DeviceLinkLock);DeviceLink *CurNode = pDeviceLink->pNext;DeviceLink *PreNode = pDeviceLink;while (CurNode != NULL){if (strcmp(DeviceName, CurNode->DeviceName) == 0){PreNode->pNext = CurNode->pNext;free(CurNode);CurNode = NULL;pthread_mutex_unlock(&DeviceLinkLock);return;}else{PreNode = CurNode;CurNode = CurNode->pNext;}}pthread_mutex_unlock(&DeviceLinkLock);return; }void NetLinkProcess(OperationQueue *pOperationQueue) {printf("NetLinkProcess ...\n");// printf("-------------NetLinkProcess-----------------\n");// printf("pOperationQueue: %x\n", pOperationQueue);// fflush(stdout);struct sockaddr_nl src_addr, dest_addr;struct nlmsghdr *nlh = NULL;struct iovec iov;int sock_fd;struct msghdr msg;sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);memset(&msg, 0, sizeof(msg));memset(&src_addr, 0, sizeof(src_addr));src_addr.nl_family = AF_NETLINK;src_addr.nl_pid = getpid(); /* self pid */// src_addr.nl_groups = 0; /* not in mcast groups */src_addr.nl_groups = 1; /* receive broadcast message*/bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.nl_family = AF_NETLINK;dest_addr.nl_pid = 0; /* For Linux Kernel */dest_addr.nl_groups = 0; /* unicast */nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));/* Fill the netlink message header */nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);nlh->nlmsg_pid = getpid(); /* self pid */nlh->nlmsg_flags = 0;/* Fill in the netlink message payload */// strcpy(NLMSG_DATA(nlh), "Hello you!");iov.iov_base = (void *)nlh;iov.iov_len = nlh->nlmsg_len;msg.msg_name = (void *)&dest_addr;msg.msg_namelen = sizeof(dest_addr);msg.msg_iov = &iov;msg.msg_iovlen = 1;while (1){memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));// printf(" Waiting message. ...\n");recvmsg(sock_fd, &msg, 0); //接收內核的消息char operation[20] = {0};strncpy(operation, (char *)nlh, 19);*(strchr(operation, '@')) = '\0';char DeviceName[NAME_MAX] = {0};strcpy(DeviceName, strrchr((char *)nlh, '/') + 1);// printf("%s ------- %s\n", operation, DeviceName);// fflush(stdout);Push_OperationQueue(pOperationQueue, operation, DeviceName);}close(sock_fd); }void ResolveOperationProcess(void *arg) {OperationQueue *pOperationQueue = ((ResolveOperationProcessParams *)arg)->pOperationQueue;DeviceLink *pDeviceLink = ((ResolveOperationProcessParams *)arg)->pDeviceLink;// printf("-------------ResolveOperationProcess-----------------\n");// printf("pDeviceLink: %x\n", pDeviceLink);// printf("((ResolveOperationProcessParams *)arg)->pDeviceLink: %x\n", ((ResolveOperationProcessParams *)arg)->pDeviceLink);// printf("pOperationQueue: %x\n", pOperationQueue);// printf("((ResolveOperationProcessParams *)arg)->pOperationQueue: %x\n", ((ResolveOperationProcessParams *)arg)->pOperationQueue);// fflush(stdout);printf("ResolveOperationProcess ...\n");char operation[20] = {0};char DeviceName[NAME_MAX] = {0};while (1){if (IsEmpty_OperationQueue(pOperationQueue)){// printf("-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");// fflush(stdout);sleep(2);continue;}// if (!Pop_OperationQueue(pOperationQueue, operation, DeviceName));// {// continue;// }// printf("-+-+-+-+-+-+-+-+-+-+-+-+-+-\n");// fflush(stdout);Pop_OperationQueue(pOperationQueue, operation, DeviceName);// printf("%s ------- %s\n", operation, DeviceName);// fflush(stdout);if (strlen(DeviceName) < 3)continue;if ('s' == DeviceName[0] && 'd' == DeviceName[1] && (DeviceName[2] >= 'a' || DeviceName[2] <= 'z')) //sda~sdz, udisk{if (0 == strcmp(operation, "add")){AddDeviceLink(0, DeviceName, "", pDeviceLink);}else if (0 == strcmp(operation, "remove")){DeleteDeviceLink(DeviceName, pDeviceLink);}else if (0 == strcmp(operation, "change")){AddDeviceLink(0, DeviceName, "", pDeviceLink);}elsecontinue;}else if ('s' == DeviceName[0] && 'r' == DeviceName[1] && (DeviceName[2] >= '0' || DeviceName[2] <= '9')) //sr0~sr9, cdrom{if (0 == strcmp(operation, "add")){AddDeviceLink(1, DeviceName, "", pDeviceLink);}else if (0 == strcmp(operation, "remove")){DeleteDeviceLink(DeviceName, pDeviceLink);}else if (0 == strcmp(operation, "change")){AddDeviceLink(1, DeviceName, "", pDeviceLink);}elsecontinue;}elsecontinue;}return; }void CheckMountProcess(DeviceLink *pDeviceLink) {printf("CheckMountProcess ...\n");while (1){// 獲取行數,用于確定創建對照表的大小int row = 0;char cmd[MAX_BUFF_LEN] = {0};char buffer[MAX_BUFF_LEN] = {0};FILE *pf;sprintf(cmd, "cat %s | grep -n \" \" | awk -F \":\" '{print $1}' | tail -n1", FILE_MOUNT_CHECK);// system(cmd);pf = popen(cmd, "r");fread(buffer, sizeof(buffer), 1, pf);row = atoi(buffer);pclose(pf);// printf("ROW: %d\n", row);char RawData[1024] = {0};FILE *fp = fopen(FILE_MOUNT_CHECK, "r");if (NULL == fp){printf("failed to open dos.txt\n");continue;}MountMap *pMountMap = (MountMap *)malloc(sizeof(MountMap) * row);if (NULL == pMountMap){printf("Malloc failed!\n");continue;}memset(pMountMap, 0, sizeof(MountMap) * row);int mapnum = 0; // 對照表實際大小while (!feof(fp)){memset(RawData, 0, sizeof(RawData));fgets(RawData, sizeof(RawData) - 1, fp); // 包含了換行符// printf("%s", RawData);if (strlen(RawData) <= 5)continue;if ((RawData[0] != '/') || (RawData[1] != 'd') || (RawData[2] != 'e') || (RawData[3] != 'v') || (RawData[4] != '/')) // 不是/dev/開頭,直接passcontinue;char DeviceName[PATH_MAX + NAME_MAX] = {0};char MountPath[PATH_MAX + NAME_MAX] = {0};strcpy(DeviceName, RawData + 5); // +5是為了去掉/dev/*strchr(DeviceName, ' ') = '\0';strcpy(MountPath, strchr(RawData, ' ') + 1);*strchr(MountPath, ' ') = '\0';// printf("DeviceName: %s \t MountPath: %s\n", DeviceName, MountPath);strcpy(pMountMap[mapnum].DeviceName, DeviceName);strcpy(pMountMap[mapnum].MountPath, MountPath);mapnum ++;}fclose(fp);UpdateDeviceLink(pDeviceLink, pMountMap, mapnum);free(pMountMap);pMountMap = NULL;sleep(2); //2秒輪詢一次}return; }int main(int argc, char *argv[]) {pthread_mutex_init(&DeviceLinkLock, NULL);pthread_mutex_init(&OperationQueueLock, NULL);DeviceLink *pDeviceLink = (DeviceLink *)malloc(sizeof(DeviceLink)); // 設備詳情鏈表if (NULL == pDeviceLink){printf("Malloc failed\n");exit(-3);}pDeviceLink->pNext = NULL;OperationQueue *pOperationQueue = (OperationQueue *)malloc(sizeof(OperationQueue)); //Netlink操作隊列if (NULL == pOperationQueue){printf("Malloc failed\n");exit(-3);}pOperationQueue->pNext = NULL;int res;pthread_t tid_NetLink;res = pthread_create(&tid_NetLink, NULL, (void *)NetLinkProcess, (void *)pOperationQueue);if (0 != res){printf("pthread_create error.\n");fflush(stdout);exit(-1);}ResolveOperationProcessParams ropargs = {pDeviceLink, pOperationQueue};// printf("-------------main-----------------\n");// printf("pDeviceLink: %x\n", pDeviceLink);// printf("ropargs.pDeviceLink: %x\n", ropargs.pDeviceLink);// printf("pOperationQueue: %x\n", pOperationQueue);// printf("ropargs.pOperationQueue: %x\n", ropargs.pOperationQueue);// fflush(stdout);pthread_t tid_OperationQueue;res = pthread_create(&tid_OperationQueue, NULL, (void *)ResolveOperationProcess, &ropargs);if (0 != res){printf("pthread_create error.\n");fflush(stdout);exit(-1);}pthread_t tid_CheckMount;res = pthread_create(&tid_CheckMount, NULL, (void *)CheckMountProcess, (void *)pDeviceLink);if (0 != res){printf("pthread_create error.\n");fflush(stdout);exit(-1);}// res = pthread_join(tid_NetLink, NULL);// if (0 != res)// {// printf("Thread joined error.\n");// fflush(stdout);// exit(-2);// }// printf("wait .........\n");while (1){sleep(5);OutputDeviceLink(pDeviceLink);// printf("Sleep .........\n");fflush(stdout);}free(pDeviceLink);pDeviceLink = NULL;free(pOperationQueue);pOperationQueue = NULL;return 0; }總結
以上是生活随笔為你收集整理的Ubuntu 1804 Desktop U盘/光驱插入监测及挂载监测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 某弹幕网分析-1
- 下一篇: 代码:用路由器模拟 神经元,以实现人工智