博文

目前显示的是 2018的博文

Android7.1 UAS移动硬盘识别问题

在RK3399 Android7.1.2上面的USB3.0口上使用一款SONY移动硬盘,接入时识别信息如下: rk3399_box:/ # [   25.497767] usb 6-1.4: new SuperSpeed USB device number 4 using xhci-hcd [   25.512350] usb 6-1.4: New USB device found, idVendor=2537, idProduct=1068 [   25.513043] usb 6-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [   25.513732] usb 6-1.4: Product: NS1068 [   25.514119] usb 6-1.4: Manufacturer: Norelsys [   25.514189] usb 6-1.4: SerialNumber: 0123456789ABCDE [   25.527826] scsi host0: uas [   29.089929] scsi 0:0:0:0: Direct-Access     ATA      TOSHIBA MQ01ABD1 1U   PQ: 0 ANSI: 6 [   29.100317] sd 0:0:0:0: [sda] 1953525168 512-byte logical blocks: (1.00 TB/932 GiB) [   29.100418] sd 0:0:0:0: [sda] 4096-byte physical blocks [   29.104389] sd 0:0:0:0: [sda] Write Protect is off [   29.105420] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA [   29.105603] xhci-hcd xhci-hcd.7.auto: ERROR Transfer event for disabled endpoint or incorrect stre

升级MacOS(Mojave)后使用git问题

将MacOS升级到Mojave版本后,使用git工具时,出现如下错误提示: guochongxindeMacBook-Pro:study guochongxin$ git status . xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun 解决方法: 执行xcode-select --install命令,会弹出一个对话框,按提示安装上相应工具即可,因为git附加了Xcode的命令。 参考资料: https://my.oschina.net/gooiem/blog/2208380 http://www.cnblogs.com/snifferhu/p/6196687.html https://stackoverflow.com/questions/32896524/invalid-active-developer-path-error-after-upgrading-to-el-capitan

Ubuntu下安装Docker

1.安装Docker        sudo apt-get install curl    curl -fsSL https://get.docker.com/ | sh   安装好后有如下提示:   If you would like to use Docker as a non-root user, you should now consider   adding your user to the "docker" group with something like:     sudo usermod -aG docker guochongxin   Remember that you will have to log out and back in for this to take effect!   可根据实际需要执行上面提示中的命令,将当前用户加到docker用户组里,避免后期需要加sudo执行。   接下来执行sudo docker run hello-world命令来验证安装情况,如有下面提示则表示安装成功:   Hello from Docker.      This message shows that your installation appears to be working correctly.       To generate this message, Docker took the following steps:        1. The Docker client contacted the Docker daemon.      2. The Docker daemon pulled the "hello-world" image from the Docker Hub.      3. The Docker daemon created a new container from that image which runs the        executable that produces the output you are currently reading.      4. The Docker daemon streamed that output to the

初试Netlink之unicast

        在之前已经了解了好几种内核态与用户态之间数据的交换方法,但那些方法都是单向的(即单工),其关系是一对一的,而Netlink Socket则是一种用于内核与用户空间之间传递信息的特殊IPC,在用户进程中,其以标准的Socket API为内核和用户之间提供了全双工的通信通道,在内核模块中则提供了一类特殊的API。相比TCP/IP socket所使用的AF_INET地址族,Netlink socket则使用AF_NETLINK地址族,每一个Netlink Socket都在Kernel的include/uapi/linux/netlink.h(linux-3.11.0-rc4,关于Netlink部分相关文档,如无注明均以该版本为基准)中定义了相应的protocol type。         在Linux  Kernel中,以模块形式去创建Netlink Socket时需要涉及到如下相关的API及数据结构:         1.创建Socket            在include/linux/netlink.h文件中,有如下的定义:            /* optional Netlink kernel configuration parameters */            struct netlink_kernel_cfg {                    unsigned int    groups;                    unsigned int    flags;                    void            (*input)(struct sk_buff *skb);                    struct mutex    *cb_mutex;                    void            (*bind)(int group);                    bool            (*compare)(struct net *net, struct sock *sk);            };            extern struct sock *__netlink_kernel_create(s

C编程使用内联汇编控制PC蜂鸣器发声

有了“内联汇编控制PC蜂鸣器”的基础了解后,我们使用内联汇编来改造“C编程控制PC蜂鸣器”一文的例子,最终的代码如下: #include <stdio.h> #include <unistd.h> #include <sys/io.h> /* The clock frequency of the i8253/i8254 PIT */ #define PIT_TICK_RATE 1193182ul void beep(unsigned int value) { unsigned int count = 0; unsigned char val; unsigned short port; if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; iopl(3); if (count) { val = 0xB6; port = 0x43; asm volatile("outb %0,%1" : : "a" (val), "dN" (port)); val = count & 0xff; port = 0x42; asm volatile("outb %0,%1" : : "a" (val), "dN" (port)); val = (count >> 8) & 0xff; asm volatile("outb %0,%1" : : "a" (val), "dN" (port)); port = 0x61;

使用EXPORT_SYMBOL

在Linux内核里,我们编写驱动程序时,如果遇到的驱动太大,需要在各个模块之间共享一些变量或函数等,此时就需要用到内核里的EXPORT_SYMBOL宏了,其在include/linux/export.h文件中定义,而最常用的有如下两个: #define EXPORT_SYMBOL(sym)                                      \         __EXPORT_SYMBOL(sym, "") #define EXPORT_SYMBOL_GPL(sym)                                  \         __EXPORT_SYMBOL(sym, "_gpl")        其中,多加了_GPL尾的量需要在使用MODULE_LICENSE()宏定义为GPL协议的模块里才能引用,不然加载驱动时会有类似Unknown symbol export_orig_gpl (err 0)的提示(该提示取自下面的例子),当然,模块之间也需要有加载先后顺序,其中EXPORT的模块需先加载,extern的后加载,不然也会有类似如上的提示。        这里的例子会用到两个源码文件,作为export的文件名为export_orig.c,作为extern的文件名为export_symbol_example.c,相应的源码如下:        export_orig.c: #include <linux/kernel.h> #include <linux/module.h> static int export_orig_normal; static int export_orig_gpl; EXPORT_SYMBOL(export_orig_normal); EXPORT_SYMBOL_GPL(export_orig_gpl); static __init int export_orig_init(void) {         printk("Enter %s\n", __func__);         export_orig_normal = 10;         expo

制造、调试OOPS

1.前言     在Linux系统里出现kernel panic时会打印OOPS信息,把当前的寄存器状态、堆栈信息、完整的Call trace都打印出来,以便我们更好的定位错误。下面我们将会自已制造一个OOPS,并采用多种方式来定位调试OOPS,以便大家更好的了解内核,深入探索内核,利用内核异常信息来定位处理问题。 2.制造OOPS     这次我们以模块的形式来制造一个OOPS,文件名为oops_example.c,内容如下:     #include <linux/kernel.h>     #include <linux/module.h>     static __init int oops_example_init(void)     {             int *p = 0;             printk("Hi OOPS!\n");             *p = 12;             return 0;     }     static __exit void oops_example_exit(void)     {             printk("Bye OOPS!\n");     }     module_init(oops_example_init);     module_exit(oops_example_exit);     相应的Makefile文件内容如下:     obj-m += oops_example.o     CUR_PATH:=$(shell pwd)     LINUX_KERNEL_PATH:=/home/xinu/linux-3.13.6     all:             make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) modules     clean:             make -C $(LINUX_KERNEL_PATH) M=$(CUR_PATH) clean     相应的源码文件目录树如下:     oops_example/{Makefile,oops_example.c}

内联汇编控制PC蜂鸣器

本文,我们对控制PC蜂鸣器的操作改为使用内联汇编的方法,里面会使用到约束“a”和“dN”,其中前者对应eax,后者对应edx,并且N表示0-255之间的数,有了这些了解后,我们改造下“I/O映射之I/O端口”里的例子,改造后的代码如下: #include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/timex.h> static int value = 0; module_param(value, int, 0644); MODULE_PARM_DESC(value, "the beep frequences(20,32767)"); static __init int ioport_beep_init(void) { unsigned int count = 0; u8 val; u16 port; if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; if (count) { /* set command for counter 2, write 2 bytes */ val = 0xB6; port = 0x43; asm volatile("outb %0,%1" : : "a" (val), "dN" (port)); /* select desired HZ */ val = count & 0xff; port = 0x42; asm volatile("outb %0,%1" : : &qu

PC蜂鸣器音乐

有了“使用procfs”、“I/O映射之I/O端口”、“内核读写磁盘文件”这三篇文章的基础后,我们将其结合,实现如下功能的实例: 1.打开传入的音乐谱文件(通过procfs接口); 2.读取音乐谱文件(以“频率”、“延时”、“频率”、“延时”、……这样的格式保存); 3.解析读取的文件; 4.将解析的数据传送去操作8254,让PC蜂鸣器弹奏文件对应的音乐。 好了,基础的内容看开头提及的文章,接下来上代码: #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/proc_fs.h> #include <asm/uaccess.h> #include <linux/timex.h> #ifndef MAX_PATH #define MAX_PATH 256 #endif #define PACKAGE_SIZE 512 extern void msleep(unsigned int msecs); struct proc_dir_entry * slam_dir = NULL; struct proc_dir_entry * slam_entry = NULL; static char * dir_name = "slam_song"; static char * entry_name = "path"; static void beep(unsigned int freq, unsigned int delay) { unsigned int count; if (freq) count = PIT_TICK_RATE / freq; else count = 20; outb_p(0xB6, 0x43); outb_p(count & 0xff, 0x42); outb((count >> 8) & 0xff, 0x42);