Linux uevent事件读取代码

1 Linux aarch64-linux-gnu-gcc
1.1 aarch64-linux-gnu-gcc
https://releases.linaro.org/components/toolchain/binaries
gcc-linaro-*.tar.xz: compiler
sysroot-linaro-*.tar.xz: root fs

xz -d xxx.tar.xz
tar xvf xxx.tar

Support legacy arm-linux-gcc binary:
Userspace binary formats - > Kernel support for 32-bit EL0

1.2 Linux libtool静态链接
libtool在link-mode时,可以使用参数:-all-static
且这个参数要放在ld之后,如下:
/bin/sh ../libtool --tag=CC \
--mode=link aarch64-linux-gnu-gcc \
-all-static 

在这里是放在aarch64-linux-gnu-gcc之后,不然提示找不到-all-static。
生成的链接命令会自动加上:-static,并且自动寻找lib*.a的静态库。

1.3 showcase
# CROSS_COMPILE = \
# /path/to/bin/aarch64-linux-gnu-

# CC means C Compiler
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld

.PHONY: clean

OBJS = src/main.o

CFLAGS = \
    -I./include

LDFLAGS =

# compile every c file to object
%.o: %.c
        $(CC) $(CFLAGS) -c $^ -o $@
# link all of the objects to uevent_mon
uevent_mon: $(OBJS)
        $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) \
            -o $@

clean:
        rm -rf $(OBJS)
        rm -rf uevent_mon

2 Android.mk文件
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

SRC_LIST := $(wildcard $(LOCAL_PATH)/*.c)
LOCAL_SRC_FILES := \
    $(SRC_LIST:$(LOCAL_PATH)/%=%)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_LDLIBS := -llog
LOCAL_MODULE := uevent_mon

#LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_TAGS := optional
$(warning #$(SRC_LIST)#)

include $(BUILD_EXECUTABLE)

Android工具链独立编译二进制,需要给aarch64-linux-android-gcc提供sysroot目录,否则无法编译。

3 源代码
// uevent DEVPATH for HiCar
#define LOG_TAG "uevent_mon"

#include <ctype.h>
#include <linux/netlink.h>
#include <poll.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>

#define UEVENT_PARAMS_MAX 512
#define BUFF_LEN  (16*1024)
#define OUT_FILE "/dev/uevent.log"

static int g_dwFd = -1;
static int time_arg = 1;
static char proc_name[64] = {'\0'};
static char out_file[128] = {'\0'};

static void write_log(const char **fmt,...)
{
    va_list arg;
    FILE *fp = NULL;

    fp = fopen(out_file, "a+");
    if (fp == NULL) {
        return ;
    }

    va_start(arg,fmt);
    vfprintf(fp,fmt,arg);
    va_end(arg);

    fclose(fp);
}

static int my_printf(const char *fmt, ...)
{
    char line[512];
    va_list arg;
    int rc = 0;

    va_start(arg, fmt);
    rc = vsnprintf(line, 511, fmt, arg);
    if (rc > 0) {
        line[rc] = '\0';
    }
    va_end(arg);

    printf(line);

    return rc;
}

static void print_usage(char *toast)
{
    const char *usage =
    "Usage: %s [OPTION...]\n"
    "    -f, --file    saved log path, "
    "</data/uevent.log> by default\n"
    "    -h, --help    print the usage\n\n"
    "HOW-TO:\n"
    "copy this command to /vendor/bin/, "
    "which is for catching the kernel "
    "uevent logs\n\n"
    "For example:\n"
    "    %s -f /sdcard/uevent.log &\n"
    "    %s &\n\n";

    if (toast) {
        my_printf(toast, proc_name);
    }
    my_printf(usage,
        proc_name,
        proc_name,
        proc_name);
}

static void PrintUeventToolVersion(void)
{
    write_log(
    "\nInitial Uevent Tools Version:Beta v1.0\n");
    write_log("Author: George Tso\n");
}

static int UeventInit()
{
    struct sockaddr_nl addr;
    int sz = 64*1024;
    int s;

    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();
    addr.nl_groups = 0xffffffff;

    s = socket(PF_NETLINK,
        SOCK_DGRAM,
        NETLINK_KOBJECT_UEVENT);
    if (s < 0) {
        return 0;
    }

    setsockopt(s,
        SOL_SOCKET,
        SO_RCVBUFFORCE,
        &sz, sizeof(sz));

    if (bind(s,
        (struct sockaddr *) &addr,
        sizeof(addr)) < 0) {
        close(s);
        return 0;
    }

    g_dwFd= s;
    return (g_dwFd > 0);
}

static int UeventNextEvent(char* buffer,
    int buffer_length)
{
    while (1) {
        struct pollfd fds;
        int nr;

        fds.fd = g_dwFd;
        fds.events = POLLIN;
        fds.revents = 0;
        nr = poll(&fds, 1, -1);

        if (nr > 0 && fds.revents == POLLIN) {
            int count = recv(g_dwFd,
                buffer, buffer_length, 0);
            if (count > 0) {
                return count;
            }
        }
    }

    return 0;
}

static void process_uevent(void)
{
    char *szBuff = (char *)malloc(BUFF_LEN);
    char *s = szBuff;
    char *szEnd = NULL;
    int dwActualLen = 0;
    char timeBuf[32];
    struct timeval tv;
    struct tm* ptm;

    memset(szBuff, 0, BUFF_LEN);

    PrintUeventToolVersion();
    my_printf("\nout file: %s\n", out_file);

    UeventInit();

    for (;;) {
        dwActualLen = UeventNextEvent(szBuff,
            BUFF_LEN - 1);
        s = szBuff;
        szEnd = s + dwActualLen;

        while (s < szEnd) {
            if (!isspace(*s)) {
                if (time_arg) {
                    gettimeofday(&tv, NULL);
                    ptm = localtime(&(tv.tv_sec));
                    strftime(timeBuf, 31,
                        "%Y-%m-%d %H:%M:%S",
                        ptm);
                    write_log(
                    "[%lu.%06lu] [%s.%06lu usec] %s\n",
                        tv.tv_sec, tv.tv_usec,
                        timeBuf, tv.tv_usec, s);
                } else {
                        write_log("%s\n", s);
                }
            } // end of  if (!isspace(*s))
            s += strlen(s) + 1;
        } // end of while
    } // end of for
}

static void parse_args(int argc, char **argv)
{
    char *p = NULL;

    if ((p = strrchr(argv[0], '/')) != NULL) {
        p++;
        strcpy(proc_name, p);
    } else {
        strcpy(proc_name, argv[0]);
    }

    argc--;
    argv++;

    while (argc > 0){
        if (!strcasecmp(argv[0], "-h") ||
           !strcasecmp(argv[0], "--help")) {
            print_usage(NULL);
            argc--;
            argv++;
            exit(0);
        } else if (!strcasecmp(argv[0], "-f") ||
           !strcasecmp(argv[0], "--file")) {
            argc--;
            argv++;
            if (argc == 0) {
                print_usage("Need argument\n");
                exit(0);
            }
            strcpy(out_file, argv[0]);
            argc--;
            argv++;
        } else {
            argc--;
            argv++;
        }
    }
}

//-----------------------------------------------------------------------------------
int main(int argc, char **argv)
{
    strcpy(out_file, OUT_FILE);
    parse_args(argc, argv);
    process_uevent();

    return 0;
}

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Linux uevent是一种事件通知机制,用于在Linux系统中检测和处理设备的插拔、状态变化等事件。当设备插入或拔出时,内核会生成一个uevent事件,通知用户空间程序进行相应的处理。这种机制可以帮助用户空间程序动态地管理设备,提高系统的可靠性和灵活性。 ### 回答2: Linux uevent是指Linux内核中与设备驱动以及设备管理有关的事件通知机制,简单来说,就是Linux实时发布与硬件设备状态相关的事件信息,供应用程序进行响应处理。 Linux uevent是从udev项目中分离出来的,uevent事件主要与设备插拔及设备状态变化有关。当有设备插入或者拔出时,Linux内核会通过uevent事件通知应用程序, 以便应用程序能够对插入/拔出操作作出正确的响应。同时,设备状态改变也会触发uevent事件,如设备上线,设备离线等。 对于应用程序开发者来说,了解Linux uevent机制非常重要。使用Linux uevent机制,可以在设备发生变化时,实时通知相应的应用程序并进行相应的操作,以提高应用程序的响应速度和用户体验。 总之,Linux uevent是一个非常重要的事件通知机制,它可以帮助开发者更好地管理设备状态,并实现自动化管理和控制,在实际应用中具有重要的作用。 ### 回答3: Linux的uevent是一个内核事件通知机制,它允许用户空间程序监控和响应Linux内核所发生的事件。内核事件通知机制旨在为用户空间提供一种优雅的方式来处理内核中的事件,而无需检查 /proc/sys 或其他系统状态文件。 这个机制从内核2.6开始就得到了广泛支持,并且在当今的Linux系统中得到了更进一步的完善。使用uevent机制,用户空间程序可以知道关于硬件和设备状态方面的任何更改;例如,当一个USB设备被插入时,将生成一个event来告知用户空间其类别及ID等详细信息。 Linux的uevent机制基于Netlink,使用了内核中的“uevent netlink”套接字。它向用户空间发送uevent信号,使用户空间程序能够检测到设备事件和状态改变等内核事件,从而支持用户空间即时响应内核事件。 在用户空间实现uevent机制的程序通常使用libudev库,这个库提供了C语言和Python的API,可用于编写应用程序并实现与uevent机制的交互。它允许用户为设备注册回调函数,并且对设备添加或删除做出响应。 总之,Linux的uevent是一种非常有用的内核事件通知机制,可以使用户空间程序更好地响应设备和硬件状态的变化。它利用了内核提供的信号和Netlink套接字方法,为开发者提供了一种便捷的方式来实现系统级的自动化操作和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值