open,close,read,perror

-- TOC --

前面的几个驱动程序,测试都用python,也该学学用C直接进行系统调用了,这样可以控制的更精确。

下面这段代码,实现了读取一个device file固定长度,并将读取的内容打印在屏幕上:

$ cat mychar_read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>


#define ERRBUF_SIZE 64
#define _PERROR \
    do { \
        char errbuf[ERRBUF_SIZE] = {0}; \
        sprintf(errbuf, "%s:%d", __FILE__, __LINE__); \
        perror(errbuf); \
    } while(0) \


int main(int argc, char **argv) {
    int i, fd;
    ssize_t cnt;
    char *rbuf;

    /* disable the unused warning */
    assert(argc == 3);

    /* open */
    if ((fd=open(argv[1],O_RDONLY)) == -1) {
        _PERROR;
        return errno;
    }

    /* alloc memory */
    i = atoi(argv[2]);
    rbuf = malloc(i);
    if (rbuf == NULL) {
        _PERROR;
        return errno;
    }
    memset(rbuf, 0, i);

    /* read */
    if ((cnt=read(fd,rbuf,i)) == -1) {
        _PERROR;
        free(rbuf);
        return errno;
    }

    /* print out */
    printf("read out %ld bytes\n", cnt);
    for (i=0; i<cnt; ++i) printf("%02X ", (unsigned char)rbuf[i]);
    if (cnt != 0) printf("\n");

    /* close */
    if (close(fd) == -1) {
        _PERROR;
        free(rbuf);
        return errno;
    }

    free(rbuf);
    return 0;
}

用到了open,close,read这3个系统调用,另外将perror封装在一个macro里面,以方便打印出具体的错误字符串,以及错误发生的位置。

查询系统调用:$ man 2 xxxx

调试过程还是肥了一点点周折,但现在写总结时,却发现似乎没啥可写的,一切似乎都是理所当然。

errno在系统调用返回错误时被设置位具体的错误码,用perror库函数可以打印出错误字符串,此函数接收一个参数,作为输出的prefix。我也用了最流行的do {...} while(0)这种结构定义macro function。errbuf不是全局的,这样可以支持多线程,而errno本就thread-safe!

这些errno,定义在内核的如下两个文件中:include/uapi/asm-generic/errno-base.hinclude/uapi/asm-generic/errno.h中!

注意如何按16进制打印char!要cast到unsigned char类型。

这么一个小小的功能,引用的头文件还不少......

用上一篇的mychar驱动,以及系统自带的伪设备测试,OK的:

$ gcc -Wall -Wextra mychar_read.c -o mychar_read
$ echo '123123' > mychar-4
$ cat mychar-4
123123
$ ./mychar_read mychar-4 4
read out 4 bytes
31 32 33 31 
$ ./mychar_read mychar-4 8
read out 7 bytes
31 32 33 31 32 33 0A 
$ ./mychar_read /dev/random 8
read out 8 bytes
BA 53 C4 8B 83 83 62 D7 
$ ./mychar_read /dev/random 16
read out 16 bytes
56 3D 00 DF 84 19 76 20 2E 5D 7E 83 28 C0 CD 05 
$ ./mychar_read mychar-8 8  # non-exist device file
mychar_read.c:29: No such file or directory

本文链接:https://cs.pynote.net/sf/linux/dd/202112262/

-- EOF --

-- MORE --