天天看點

Linux uevent事件讀取代碼

1 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 Makefile靜态連結

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的靜态庫。

https://www.gnu.org/software/libtool/manual/html_node/Link-mode.html

1.3 showcase

# CROSS_COMPILE = \

# /path/to/bin/aarch64-linux-gnu-

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 [email protected]

# link all of the objects to uevent_mon

uevent_mon: $(OBJS)

        $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) \

            -o [email protected]

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_MODULE_TAGS := optional

$(warning #$(LOCAL_MODULE_TAGS)#)

$(warning #$(SRC_LIST)#)

include $(BUILD_EXECUTABLE)

3 源代碼

#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;

}

繼續閱讀