试跳第贰个hello world模块添加:

一.环境如下:

make
menuconfig进程解析
作者
codercjg
在 28 九月 2015, 5:27 下午

1.地点主机的参数

zhangjun@zhangjun-virtual-machine:~$ uname -a

Linux zhangjun-virtual-machine 4.4.0-31-generic #50~14.04.1-Ubuntu SMP
Wed Jul 13 01:07:32 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

zhangjun@zhangjun-virtual-machine:~$ ls
/usr/src/linux-headers-4.4.0-31-generic/arch    Documentation  include 
Kconfig   mm              scripts   tools   zfs

block   drivers        init     kernel    Module.symvers  security 
ubuntu

certs   firmware       ipc      lib       net             sound     usr

crypto  fs             Kbuild   Makefile  samples         spl       virt

 

1,在添加drivers/char/hello.c

1.1基石版本:

make menuconfig用于图形界面配置linux内核。
linux源码根目录下有.config文件,别的子目录下一般都会有二个Kconfig文件和Makefile文件。
多个文本的意义分别为:
Kconfig: 定义配置项
.config: 设置配置项的值(可经过make menuconfig界面配置可能直接修改)
Makefile:读取配置项的值,并依据该值决定是不是编写翻译该目录下该配置项事关的c源文件

2.编纂内核模块文件

编纂自身的内核模块文件myModule.c,内容如下:

#include  <linux/kernel.h>

#include <linux/module.h>

#include <linux/types.h>

static int __init myModule_init(void)

{

    printk(KERN_INFO”myModule init.\r\n”);

        return 0;

}

 

static void __exit myModule_exit(void)

{

    printk(KERN_INFO”myModule exit.\r\n”);

}

module_init(myModule_init);

module_exit(myModule_exit);

MODULE_LICENSE(“GPL”);

 

/*********************************************************************************
 *      Copyright:  (C) 2014
zhouguangfeng<zhouguangfeng91@gmail.com>
 *                  All rights reserved.
 *
 *       Filename:  hello.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(08/09/2014)
 *         Author:  zhouguangfeng <zhouguangfeng91@gmail.com>
 *      ChangeLog:  1, Release initial version on “08/09/2014 06:23:18
PM”
 *                 
 ********************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

jello@jello:~$ uname -a

make menuconfig 首先会读取/arch/arm/Kconfig,
然后依照该Kconfig文件引用其余目录下的Kconfig,
说到底和根目录下的.config相比,生成图形配置界面,配置完毕后的结果保存在.config文件中。
例如当写1个hello的字符驱动hello.c后,放在linux源码/driver/char/目录下后,要联手工编织译进基本须要
修改该目录下的Kconfig和Makefile.
在/driver/char/Kconfig文件里参与以下内容:
config HELLO
bool “/dev/hello hello driver example ”
default y
help
Say Y here if you want to support /dev/hello device.
然后make menuconfig后就能够看看如下内容:

3.编写Makefile

#kernel代码的路径

KERN_DIR = /usr/src/linux-headers-4.4.0-31-generic/   

all:

         make -C $(KERN_DIR) M=`pwd` modules   

clean:   

         make -C $(KERN_DIR) M=`pwd` modules clean   

obj-m += myModule.o

MODULE_LICENSE (“Dual BSD/GPL”);

Linux jello 4.4.0-89-generic #112-Ubuntu SMP Mon Jul 31 19:38:41 UTC
2017 x86_64 x86_64 x86_64 GNU/Linux

澳门金沙国际 1

4.编译

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# make

make -C /usr/src/linux-headers-4.4.0-31-generic/     M=`pwd`
modules   

make[1]: 正在进入目录 `/usr/src/linux-headers-4.4.0-31-generic’

  CC [M]  /home/zhangjun/zj_driver/myModule/myModule.o

  Building modules, stage 2.

  MODPOST 1 modules

  CC      /home/zhangjun/zj_driver/myModule/myModule.mod.o

  LD [M]  /home/zhangjun/zj_driver/myModule/myModule.ko

make[1]:正在离开目录 `/usr/src/linux-headers-4.4.0-31-generic’

 

static int __init hello_init (void)
{
    printk (KERN_INFO “Hello world\n”);
    return 0;
}

1.2发行版:

但此时执行make
zImage还不可能编写翻译成功,要科学编写翻译还亟需在/driver/char/Makefile文件里增加:
obj-$(CONFIG_HELLO)+= hello.o
当在make
menuconfig图形界面里选中了hello选项后,生成的.config文件会有CONFIG_HELLO=y
当执行make zImage命令时,obj-y += hello.o
就意味着要把该目的文件编写翻译进基本。
倘倘若模块,则可把HELLO配置项设为tristate类型,在make
menuconfig图形界面采用hello M模块选项时
生成的.config文件会CONFIG_HELLO=m
当执行make modules命令时,obj-m +=hell.o就意味着把该目的文件编译为模块。
obj-y和obj-m是linux
编译时定义的全局变量,分别代表要编译进基本的公文列表和编写翻译为模块的文件列表。

5.装置驱动

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule#
insmod myModule.ko

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# cat
/proc/modules

myModule 16384 0 – Live 0xffffffffc03d4000 (OE)

nls_utf8 16384 1 – Live 0xffffffffc016f000

isofs 40960 1 – Live 0xffffffffc03f4000

vmw_vsock_vmci_transport 28672 1 – Live 0xffffffffc03cc000

vsock 36864 2 vmw_vsock_vmci_transport, Live 0xffffffffc0165000

bnep 20480 2 – Live 0xffffffffc0178000

rfcomm 69632 8 – Live 0xffffffffc050b000

nfsd 315392 13 – Live 0xffffffffc05e4000

auth_rpcgss 57344 1 nfsd, Live 0xffffffffc0542000

nfs_acl 16384 1 nfsd, Live 0xffffffffc038b000

nfs 249856 0 – Live 0xffffffffc05a6000

binfmt_misc 20480 1 – Live 0xffffffffc0393000

lockd 90112 2 nfsd,nfs, Live 0xffffffffc052b000

grace 16384 2 nfsd,lockd, Live 0xffffffffc0386000

sunrpc 331776 19 nfsd,auth_rpcgss,nfs_acl,nfs,lockd, Live
0xffffffffc04b9000

fscache 61440 1 nfs, Live 0xffffffffc04a9000

coretemp 16384 0 – Live 0xffffffffc03c7000

kvm_intel 167936 0 – Live 0xffffffffc057c000

kvm 532480 1 kvm_intel, Live 0xffffffffc0426000

snd_ens1371 28672 2 – Live 0xffffffffc0365000

snd_ac97_codec 131072 1 snd_ens1371, Live 0xffffffffc0405000

irqbypass 16384 1 kvm, Live 0xffffffffc0381000

crct10dif_pclmul 16384 0 – Live 0xffffffffc037c000

gameport 16384 1 snd_ens1371, Live 0xffffffffc0373000

crc32_pclmul 16384 0 – Live 0xffffffffc034b000

ac97_bus 16384 1 snd_ac97_codec, Live 0xffffffffc0400000

snd_pcm 106496 2 snd_ens1371,snd_ac97_codec, Live 0xffffffffc03d9000

aesni_intel 167936 0 – Live 0xffffffffc039d000

vmw_balloon 20480 0 – Live 0xffffffffc036d000

snd_seq_midi 16384 0 – Live 0xffffffffc0360000

snd_seq_midi_event 16384 1 snd_seq_midi, Live 0xffffffffc035b000

aes_x86_64 20480 1 aesni_intel, Live 0xffffffffc0355000

lrw 16384 1 aesni_intel, Live 0xffffffffc0321000

gf128mul 16384 1 lrw, Live 0xffffffffc0350000

snd_rawmidi 32768 2 snd_ens1371,snd_seq_midi, Live
0xffffffffc0342000

glue_helper 16384 1 aesni_intel, Live 0xffffffffc033d000

ablk_helper 16384 1 aesni_intel, Live 0xffffffffc0277000

cryptd 20480 2 aesni_intel,ablk_helper, Live 0xffffffffc031b000

joydev 20480 0 – Live 0xffffffffc0315000

input_leds 16384 0 – Live 0xffffffffc0307000

serio_raw 16384 0 – Live 0xffffffffc0233000

snd_seq 69632 2 snd_seq_midi,snd_seq_midi_event, Live
0xffffffffc032b000

snd_seq_device 16384 3 snd_seq_midi,snd_rawmidi,snd_seq, Live
0xffffffffc0326000

snd_timer 32768 2 snd_pcm,snd_seq, Live 0xffffffffc030c000

btusb 45056 0 – Live 0xffffffffc02fb000

btrtl 16384 1 btusb, Live 0xffffffffc0272000

btbcm 16384 1 btusb, Live 0xffffffffc0160000

btintel 16384 1 btusb, Live 0xffffffffc0145000

bluetooth 516096 25 bnep,rfcomm,btusb,btrtl,btbcm,btintel, Live
0xffffffffc027c000

snd 81920 11
snd_ens1371,snd_ac97_codec,snd_pcm,snd_rawmidi,snd_seq,snd_seq_device,snd_timer,
Live 0xffffffffc021e000

soundcore 16384 1 snd, Live 0xffffffffc006b000

nfit 32768 0 – Live 0xffffffffc01f0000

vmwgfx 229376 3 – Live 0xffffffffc0239000

ttm 94208 1 vmwgfx, Live 0xffffffffc01d8000

drm_kms_helper 143360 1 vmwgfx, Live 0xffffffffc01fa000

drm 360448 6 vmwgfx,ttm,drm_kms_helper, Live 0xffffffffc017f000

shpchp 36864 0 – Live 0xffffffffc0156000

fb_sys_fops 16384 1 drm_kms_helper, Live 0xffffffffc0151000

syscopyarea 16384 1 drm_kms_helper, Live 0xffffffffc014c000

vmw_vmci 65536 2 vmw_vsock_vmci_transport,vmw_balloon, Live
0xffffffffc0134000

sysfillrect 16384 1 drm_kms_helper, Live 0xffffffffc00fc000

sysimgblt 16384 1 drm_kms_helper, Live 0xffffffffc00b8000

i2c_piix4 24576 0 – Live 0xffffffffc0120000

8250_fintek 16384 0 – Live 0xffffffffc00f7000

parport_pc 36864 0 – Live 0xffffffffc00ae000

ppdev 20480 0 – Live 0xffffffffc0065000

mac_hid 16384 0 – Live 0xffffffffc003d000

lp 20480 0 – Live 0xffffffffc0043000

parport 49152 3 parport_pc,ppdev,lp, Live 0xffffffffc0030000

hid_generic 16384 0 – Live 0xffffffffc004d000

usbhid 49152 0 – Live 0xffffffffc0127000

hid 118784 2 hid_generic,usbhid, Live 0xffffffffc0102000

psmouse 122880 0 – Live 0xffffffffc00d8000

mptspi 24576 2 – Live 0xffffffffc00cd000

mptscsih 40960 1 mptspi, Live 0xffffffffc00be000

mptbase 102400 2 mptspi,mptscsih, Live 0xffffffffc0072000

e1000 135168 0 – Live 0xffffffffc008c000

scsi_transport_spi 32768 1 mptspi, Live 0xffffffffc0052000

ahci 36864 1 – Live 0xffffffffc005b000

libahci 32768 1 ahci, Live 0xffffffffc0027000

pata_acpi 16384 0 – Live 0xffffffffc000f000

fjes 28672 0 – Live 0xffffffffc001f000

vmw_pvscsi 24576 0 – Live 0xffffffffc0014000

vmxnet3 57344 0 – Live 0xffffffffc0000000

安装驱动应该会调用myModule_init函数,那么应该有打印输出,不过事实上并未;

 

static void __exit hello_exit (void)
{
    printk (KERN_INFO “Goodbye world\n”);
    return;
}

jello@jello:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial

任何连锁命令:
make clean 清除编译内核生成的有关文书
make distclean
清除编写翻译内核生成的相关文件,并且删除根目录下的.config文件
make xxxx_defconfig
会依照/arch/arm/configs/目录下的xxx_defconfig配置文件生成根目录下的.config文件。

6.卸载驱动

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# rmmod
myModule.ko

 

module_init (hello_init);
module_exit (hello_exit);

 

分类:
Linux驱动
|
评论

7.模块安装时的打字与印刷

手续5在安装myModule.ko的时候终端上并不曾打字与印刷出音信,不过事实上打字与印刷的音信写入文件/var/log/kern.log,能够通过tail命令查看该公文最后的条款。

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# tail
-f /var/log/kern.log

Jan 15 11:17:16 zhangjun-virtual-machine kernel: [ 5755.442589]
myModule: module verification failed: signature and/or required key
missing – tainting kernel

Jan 15 11:17:16 zhangjun-virtual-machine kernel: [ 5755.448875]
myModule init.

Jan 15 11:21:12 zhangjun-virtual-machine kernel: [ 5991.177018]
myModule exit.

 

里头 printk是水源特有的打字与印刷函数,类似与printf,只是它不信赖库文件,KE索罗德N_INFO为

二.列出启用的模块:

platform总线设备驱动模型
作者
codercjg
在 28 九月 2015, 3:57 下午

8.关于printk函数

Linux 内核中经过printk输出新闻,音信的系列在文件/usr/src/
linux-headers-4.4.0-31-generic
/include/linux/printk.h中(有个别源码在文书include\linux\kernel.h中)定义。

/*

 * These can be used to print at the various log levels.

 * All of these will print unconditionally, although note that
pr_debug()

 * and other debug macros are compiled out unless either DEBUG is
defined

 * or CONFIG_DYNAMIC_DEBUG is set.

 */

#define pr_emerg(fmt, …) \

         printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)

#define pr_alert(fmt, …) \

         printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)

#define pr_crit(fmt, …) \

         printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)

#define pr_err(fmt, …) \

         printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)

#define pr_warning(fmt, …) \

         printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)

#define pr_warn pr_warning

#define pr_notice(fmt, …) \

         printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)

#define pr_info(fmt, …) \

         printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)

假定不点名,暗中同意是 DEFAULT_MESSAGE_LOGLEVE,和KERN_WARNING一样。 
root@vickytong:/usr/src/ linux-headers-4.4.0-31-generic# find . -name
“*.h” | xargs grep “DEFAULT_MESSAGE_LOGLEVE”

./include/generated/autoconf.h: #define
CONFIG_MESSAGE_LOGLEVEL_DEFAULT 4

 

打字与印刷优先级

jello@jello:~$ lsmod
Module Size Used by

linux设备驱动模型中分总线、设备、驱动四个重点概念。
各样设备都要挂在一种总线上,比如MCU外部引脚引出的i2c、spi等,但是在MCU内部的i2c控制器、spi控制器等却不在任何总线上。
由此,linux抽象出platform总线的定义,MCU内部的各类设备都可挂在platform总线上。
platform设备驱动的步调:
platform_device_register()=>platform_driver_register()=>platform_driver_unregister()=>platform_device_unregister()
platform设备驱动分为八个:多少个平台设备platform_device和三个平台驱动platform_driver。
下边是三个最简易的platform hello驱动
hello-device.c源码

9.陆续编写翻译

有时候大家供给将模块移植到任何芯片方案的主机(或开发板)上运转,那么要求交叉编写翻译。交叉编写翻译要求修改Makefile,重倘若修改kernel代码的门径和编写翻译工具。kernel代码的门径要修改为指标主机系统的源代码路径,编写翻译工具gcc要修改为目标主机芯片架构对应的编写翻译工具。 设置编译器,与编写翻译内核用的编写翻译器要平等。上面为编写翻译驱动时,在terminal终端安装环境变量如下:

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule#
source /opt/Xilinx/SDK/2015.4/settings64.sh

 

root@zhangjun-virtual-machine:/home/zhangjun/zj_1个粗略的内核模块例子,驱动模块添加。driver/myModule#
export ARCH=arm

 

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# 
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-

 

注解:在脚下ZedBoard上跑的linux系统,使用该编写翻译器就好像也能编写翻译驱动插入到基本中去(前边做gpio驱动时仔细验证):

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule#
export ARCH=arm

 

root@zhangjun-virtual-machine:/home/zhangjun/zj_driver/myModule# 
export CROSS_COMPILE= arm-linux-gnueabihf-

 

makefile文件修改如下:

#kernel代码的门径

KERN_DIR = /home/zhangjun/linux 

obj-m := myModule.o

all:

     make -C $(KERN_DIR) ARCH=arm M=`pwd` modules 

clean:     

     rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions

 

 

2,修改drivers/char/Kconfig文件,添加在make
menuconfig的选项

ipt_MASQUERADE 16384 1   (数据包伪装)
nf_nat_masquerade_ipv4 16384 1 ipt_MASQUERADE  (This is the kernel
functionality to provide NAT in the masquerade flavour (automatic source
address selection).这是提供NAT的根本功用)
nf_conntrack_netlink 40960 0 (Connection tracking netlink interface
追踪网络链接接口的连日)
nfnetlink 16384 2 nf_conntrack_netlink (new netfilter netlink
interface 新的互连网过滤链接接口)
xfrm_user 32768 1  (Transformation user configuration
interface转变用户配置的接口)
xfrm_algo 16384 1 xfrm_user ()
iptable_nat 16384 1  (nat相关)
nf_conntrack_ipv4 16384 2  (IPv4 connection tracking support (required
for NAT)ipv4连接追踪帮衬(NAT供给此帮助))
nf_defrag_ipv4 16384 1 nf_conntrack_ipv4
nf_nat_ipv4 16384 1 iptable_nat
澳门金沙国际 ,xt_addrtype 16384 2
iptable_filter 16384 1
ip_tables 24576 2 iptable_filter,iptable_nat
xt_conntrack 16384 1
x_tables 36864 5
ip_tables,ipt_MASQUERADE,xt_conntrack,iptable_filter,xt_addrtype
nf_nat 24576 2 nf_nat_ipv4,nf_nat_masquerade_ipv4
nf_conntrack 106496 6
nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_netlink,nf_conntrack_ipv4
br_netfilter 24576 0
bridge 126976 1 br_netfilter
stp 16384 1 bridge
llc 16384 2 stp,bridge
aufs 217088 0
psmouse 131072 0
pci_stub 16384 1
vboxpci 24576 0
vboxnetadp 28672 0
vboxnetflt 28672 0
vboxdrv 454656 3 vboxnetadp,vboxnetflt,vboxpci
binfmt_misc 20480 1
dell_wmi 16384 0
sparse_keymap 16384 1 dell_wmi
uvcvideo 90112 0
videobuf2_vmalloc 16384 1 uvcvideo
videobuf2_memops 16384 1 videobuf2_vmalloc
videobuf2_v4l2 28672 1 uvcvideo
videobuf2_core 36864 2 uvcvideo,videobuf2_v4l2
v4l2_common 16384 1 videobuf2_v4l2
videodev 176128 4
uvcvideo,v4l2_common,videobuf2_core,videobuf2_v4l2
media 24576 2 uvcvideo,videodev
intel_rapl 20480 0
dell_laptop 20480 0
x86_pkg_temp_thermal 16384 0
dcdbas 16384 1 dell_laptop
intel_powerclamp 16384 0
dell_smm_hwmon 16384 0
coretemp 16384 0
kvm_intel 172032 0
kvm 544768 1 kvm_intel
irqbypass 16384 1 kvm
crct10dif_pclmul 16384 0
crc32_pclmul 16384 0
ghash_clmulni_intel 16384 0
wl 6447104 0
snd_hda_codec_hdmi 53248 1
cryptd 20480 1 ghash_clmulni_intel
snd_hda_codec_idt 57344 1
snd_hda_codec_generic 77824 1 snd_hda_codec_idt
snd_hda_intel 40960 6
snd_hda_codec 135168 4
snd_hda_codec_hdmi,snd_hda_codec_idt,snd_hda_codec_generic,snd_hda_intel
snd_hda_core 73728 5
snd_hda_codec_hdmi,snd_hda_codec_idt,snd_hda_codec_generic,snd_hda_codec,snd_hda_intel
snd_hwdep 16384 1 snd_hda_codec
snd_pcm 106496 4
snd_hda_codec_hdmi,snd_hda_codec,snd_hda_intel,snd_hda_core
snd_seq_midi 16384 0
snd_seq_midi_event 16384 1 snd_seq_midi
snd_rawmidi 32768 1 snd_seq_midi
snd_seq 69632 2 snd_seq_midi_event,snd_seq_midi
snd_seq_device 16384 3 snd_seq,snd_rawmidi,snd_seq_midi
snd_timer 32768 2 snd_pcm,snd_seq
cfg80211 565248 1 wl
input_leds 16384 0
joydev 20480 0
serio_raw 16384 0
snd 81920 23
snd_hwdep,snd_timer,snd_hda_codec_hdmi,snd_hda_codec_idt,snd_pcm,snd_seq,snd_rawmidi,snd_hda_codec_generic,snd_hda_codec,snd_hda_intel,snd_seq_device
soundcore 16384 1 snd
mei_me 36864 0
mei 98304 1 mei_me   (Intel Management Engine Interface:

include <linux/module.h>

10.下载、安装和卸载

         在Zedboard上的linux挂在nfs,在Terminal上做如下操作:

analog@analog:~$ sudo mount -t nfs 192.168.0.25:/home/zhangjun /mnt/

mount.nfs: /mnt is busy or already mounted

analog@analog:~$ cd /mnt

analog@analog:/mnt$ cd zj_driver

analog@analog:/mnt/zj_driver$ ls

driver_demo  myModule

analog@analog:/mnt/zj_driver$ cd myModule

analog@analog:/mnt/zj_driver/myModule$ ls

Makefile   Module.symvers  myModule.c   myModule.ko     myModule.mod.o

Makefile~  modules.order   myModule.c~  myModule.mod.c  myModule.o

analog@analog:/mnt/zj_driver/myModule$ insmod myModule.ko

insmod: ERROR: could not insert module myModule.ko: Operation not
permitted

analog@analog:/mnt/zj_driver/myModule$ sudo su

root@analog:/mnt/zj_driver/myModule# insmod myModule.ko

root@analog:/mnt/zj_driver/myModule# cat /proc/modules

myModule 737 0 – Live 0xbf000000 (O)

root@analog:/mnt/zj_driver/myModule# rmmod myModule.ko

 

#
# Character device configuration
#

The Intel Management Engine (Intel ME) is an isolated and 
protected computing resources (Coprocessor) residing inside 
Intel chipsets. The Intel ME provides support for computer/IT 
management features.
The Feature set depends on Intel chipset SKU.(摘自https://lwn.net/Articles/440292/)

因特尔管理引擎是一个被分离和被保护的属于因特尔芯片组里面的计算资源(协处理器),这个因特尔管理引擎为computer/IT提供管理特性,这种特性集取决于因特尔芯片组SKU,更多资料请看:https://cateee.net/lkddb/web-lkddb/INTEL_MEI.html

include <linux/kernel.h>

11.添加模块参数

奇迹供给从用户态传参数给内核模块,那时候在内核模块中须求通过宏module_param评释参数。本例扩大八个参数,三个是字符串参数cString,二个是int型参数iInt,修改后代码如下:

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/types.h>

 

static char* cString = NULL;

static int iInt = 0;

module_param(cString, charp, 0644);

module_param(iInt, int, 0644);

 

static int __init myModule_init(void)

{

    printk(KERN_INFO”myModule init, cString = %s, iInt = %d\r\n”,
cString, iInt);

    return 0;

}

 

static void __exit myModule_exit(void)

{

    printk(KERN_INFO”myModule exit.\r\n”);

}

module_init(myModule_init);

module_exit(myModule_exit);

MODULE_LICENSE(“GPL”);

 

穿插编写翻译后,下载,安装命令如下:

/tmp # insmod myModule.ko cString=helloworld iInt=100 
myModule init, cString = helloworld, iInt = 100

 

menu “Character devices”

)
shpchp 36864 0
mac_hid 16384 0
lpc_ich 24576 0
nfsd 319488 13
auth_rpcgss 61440 1 nfsd
nfs_acl 16384 1 nfsd
lockd 94208 1 nfsd
grace 16384 2 nfsd,lockd
parport_pc 32768 0
sunrpc 335872 18 nfsd,auth_rpcgss,lockd,nfs_acl
ppdev 20480 0
lp 20480 0
parport 49152 3 lp,ppdev,parport_pc
autofs4 40960 2
ums_realtek 20480 0
uas 24576 0
usb_storage 69632 2 uas,ums_realtek
amdkfd 131072 1
amd_iommu_v2 20480 1 amdkfd
radeon 1515520 2
i915 1208320 6
ttm 98304 1 radeon
i2c_algo_bit 16384 2 i915,radeon
drm_kms_helper 155648 2 i915,radeon
syscopyarea 16384 1 drm_kms_helper
ahci 36864 3
sysfillrect 16384 1 drm_kms_helper
libahci 32768 1 ahci
sysimgblt 16384 1 drm_kms_helper
fb_sys_fops 16384 1 drm_kms_helper
r8169 81920 0
drm 364544 12 ttm,i915,drm_kms_helper,radeon
mii 16384 1 r8169
wmi 20480 1 dell_wmi
video 40960 3 i915,dell_wmi,dell_laptop
fjes 28672 0  

include <linux/platform_device.h>

void hello_device_release(struct device *dev)
{
printk(“hello_device_release\n”);
}
struct platform_device hello_device = {
.name = “hello”,
.id = -1,
.dev = {
.release = hello_device_release,
},
};
static int __init hello_device_init(void)
{
int ret;
printk(“hello_device_init\n”);
ret = platform_device_register(&hello_device);
if(ret){
printk(“platform_device_register failed\n”);
}
return ret;
}
static void __exit hello_device_exit(void)
{
platform_device_unregister(&hello_device);
printk(“hello_device_exit\n”);
}
MODULE_AUTHOR(“codercjg”);
MODULE_LICENSE(“Dual BSD/GPL”);
module_init(hello_device_init);
module_exit(hello_device_exit);
hello-driver.c源码

source “drivers/tty/Kconfig”

 

include <linux/module.h>

# add  by zhouguangfeng 2014.8.9 for “Hello
world” 

 

include <linux/kernel.h>

config FL_HELLO
    tristate “CCTE2440 Hello Driver”
    depends on ARCH_S3C2440
    help
    FL2440 Hello Module.

未完待续…

include <linux/platform_device.h>

int hello_probe(struct platform_device *pdev)
{
printk(“hello_probe\n”);
return 0;
}
int hello_remove(struct platform_device *pdev)
{
printk(“hello_remove\n”);
return 0;
}
struct platform_driver hello_driver = {
.probe = hello_probe,
.remove = hello_remove,
.driver = {
.name = “hello”,
},
};
static int __init hello_driver_init(void)
{
int ret;
printk(“hello_driver_init\n”);
ret = platform_driver_register(&hello_driver);
if(ret){
printk(“hello_driver_init failed\n”);
}
return ret;
}
static void __exit hello_driver_exit(void)
{
platform_driver_unregister(&hello_driver);
printk(“hello_driver_exit\n”);
}
MODULE_AUTHOR(“codercjg”);
MODULE_LICENSE(“Dual BSD/GPL”);
module_init(hello_driver_init);
module_exit(hello_driver_exit);
Makefile源码
obj-m := hello-device.o hello-driver.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
.PHONY: clean
clean:
rm -rf *.o *.ko
编译后执行命令:
sudo inmod ./hello-device.ko
sudo inmod ./hello-driver.ko
hello-device和hello-driver通过.name = “hello” 匹配
其后可在 /sys/bus/platform/devices/和 /sys/devices/platform/下找到hello

分类:
Linux驱动
|
评论

队列文件seq_file
作者
codercjg
在 25 九月 2015, 5:16 下午

seq_file可在/proc下开创二个文书用于表示内核中的数据,用户能够用cat命令打印其剧情。
福寿绵绵proc文件须要三个向该文件填充内核数据的迭代器seq_operations和用户读写该公文的接口file_operations。
seq_operations中包含seq_start、seq_show、seq_next、seq_stop等迭代器相关函数。
file_operations中包含seq_open、seq_read、seq_lseek、seq_release等proc文件操作相关函数,
这么些函数在基础源码/fs/seq_file中有默许完毕,平日只需改写seq_open。
1.源码:

3,修改drivers/char/Makefile,编写翻译添加的hello.c

include <linux/module.h>

obj-$(CONFIG_FL_HELLO) += hello.o

include <linux/kernel.h>

4,make menuconfig选项

include <linux/proc_fs.h>

[*] Enable loadable module support
 —> 

include <linux/seq_file.h>

static char* strs[] = {“aa”, “bb”, “c”};
/* 迭代开端 /
static void
seq_start(struct seq_file m, loff_t pos)
{
printk(“seq_start\n”);
if(pos >= 3){
return NULL;
}
else {
pos = 0;
return strs[pos];
}
}
/
迭代下贰个 /
static void
seq_next(struct seq_file m, void v, loff_t pos)
{
printk(“seq_next\n”);
if(++
pos >= 3){
return NULL;
}
else{
return strs[pos];
}
}
/
迭代身故 */
static void seq_stop(struct seq_file *m, void v)
{
printk(“seq_stop\n”);
}
/
写当前因素到proc文件 */
static int seq_show(struct seq_file m, void v)
{
printk(“seq_show\n”);
seq_printf(m, “%s”, (char)v);
return 0;
}
/
迭代器 /
static struct seq_operations seqops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
.show = seq_show,
};
/
打开proc文件 */
int my_seq_open(struct inode inode, struct file file)
{
printk(“seq_open\n”);
return seq_open(file, &seqops);
}
/ proc文件操作接口 /
static struct file_operations fileops = {
.open = my_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int __init myproc_init(void)
{
struct proc_dir_entry entry;
entry = proc_create(“myproc”, 777, NULL, &fileops); /

创建/proc/myproc文件 /
if(!entry){
printk(“create /proc/myproc error\n”);
remove_proc_entry(“myproc”, NULL);
return -1;
}
printk(“create /proc/myproc ok\n”);
return 0;
}
static void __exit myproc_exit(void)
{
remove_proc_entry(“myproc”, NULL); /
删除/proc/myproc文件 */
printk(“remove /proc/myproc ok\n”);
}
MODULE_AUTHOR(“codercjg”);
MODULE_LICENSE(“Dual BSD/GPL”);
module_init(myproc_init);
module_exit(myproc_exit);
2.翻看结果
sudo inmod seqfile.ko
sudo cat/proc/myproc
会打字与印刷出aabbcc
3.查看日志
tail -f /var/log/syslog查看日志:
Sep 25 10:41:48 instant-contiki kernel: [ 539.889249] create
/proc/myproc ok
Sep 25 10:42:05 instant-contiki kernel: [ 556.951100] seq_open
Sep 25 10:42:05 instant-contiki kernel: [ 556.951130] seq_start
Sep 25 10:42:05 instant-contiki kernel: [ 556.951131] seq_show
Sep 25 10:42:05 instant-contiki kernel: [ 556.951133] seq_next
Sep 25 10:42:05 instant-contiki kernel: [ 556.951133] seq_show
Sep 25 10:42:05 instant-contiki kernel: [ 556.951134] seq_next
Sep 25 10:42:05 instant-contiki kernel: [ 556.951135] seq_show
Sep 25 10:42:05 instant-contiki kernel: [ 556.951136] seq_next
Sep 25 10:42:05 instant-contiki kernel: [ 556.951137] seq_stop
Sep 25 10:42:05 instant-contiki kernel: [ 556.951249] seq_start
Sep 25 10:42:05 instant-contiki kernel: [ 556.951250] seq_stop
Sep 25 10:43:11 instant-contiki kernel: [ 622.739478] remove
/proc/myproc ok
4.总结:
由源码和日志可见写入myproc文件是由此迭代器用seq_printf()一个成分三个成分的写入,。
先是调用seq_start()得到第多少个因素,然后调用seq_printf()写入myproc文件,
然后调用seq_next()获取下叁个要素,接着调用seq_printf(),直到seq_next()返回NULL后调用seq_stop()迭代了却。
即seq_start()->seq_show()->seq_next()->seq_show()->…->seq_next()->seq_stop();
sodu rmmod seqfile后,/proc/myproc文件没有了。

分类:
Linux驱动
|
评论

linux
MISC设备驱动写法
作者
codercjg
在 23 九月 2015, 4:40 下午

在编写字符设备驱动进度中,驱动入口函数中常有部分alloc_chrdev_region()分配程序设备号,
device_create()成立设备节点/dev/xxx,cdev_init()和cdev_add()注册为字符驱动等共性操作。
而讲话函数又要求收回设备号、删除设备节点、卸载字符驱动等。
为了简化字符设备驱动的编辑撰写,出现了MISC设备驱动,它只要求调用misc_register()和misc_deregister()
即可实现字符设备驱动的入口函数和出口函数相关操作。在linux源码drivers/char/misc.c中可找到misc的切实可行落到实处。
misc设备驱动本质仍为字符设备驱动,只是有所misc设备的主设备号为10,依照次设备号和装备节点名对实际设备实行区分。
次设备号和设施节点名可在使得中定义的struct miscdevice变量中钦命。

一般性字符设备驱动
struct class *hello_class;
int globalfifo_init(void)
{
int ret;
dev_t devno = MKDEV(globalfifo_major, 0);
if (globalfifo_major) {
ret = register_chrdev_region(devno, 1, “globalfifo”);
} else {
// 动态分配主设备号
ret = alloc_chrdev_region(&devno, 0, 1, “globalfifo”);
globalfifo_major = MAJOR(devno);
}
if (ret < 0)
return ret;
memset(&fifodev, 0, sizeof(struct globalfifo_dev));
cdev_init(&fifodev.cdev, &globalfifo_fops);
fifodev.cdev.owner = THIS_MODULE;
cdev_add(&fifodev.cdev, devno, 1);
sema_init(&fifodev.sem, 1);
init_waitqueue_head(&fifodev.r_wait);
init_waitqueue_head(&fifodev.w_wait);

// 创建设备节点/dev/byte
hello_class = class_create(THIS_MODULE, “fifo_class”);
device_create(hello_class, NULL, MKDEV(globalfifo_major, 0), NULL, “byte”);
printk(KERN_INFO”fifo_init\n”);
return 0; // 记得要有返回值,否则insmod的时候会提示出错

}

void globalfifo_exit(void)
{
// 删除设备节点/dev/byte
device_destroy(hello_class, MKDEV(globalfifo_major, 0));
class_destroy(hello_class);
cdev_del(&fifodev.cdev);
unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);
printk(KERN_INFO”fifo_exit\n”);
}
module_init(globalfifo_init);
module_exit(globalfifo_exit);

misc设备驱动:
static struct miscdevice misc = {
** .minor = MISC_DYNAMIC_MINOR,**
** .name = “byte”,**
** .fops = &globalfifo_fops,**
};

int globalfifo_init(void)
{
int ret;
memset(&fifodev, 0, sizeof(struct globalfifo_dev));
sema_init(&fifodev.sem, 1);
init_waitqueue_head(&fifodev.r_wait);
init_waitqueue_head(&fifodev.w_wait);

** ret = misc_register(&misc);**
printk(KERN_INFO”fifo_init\n”);
return ret; // 记得要有重回值,不然insmod的时候会提醒出错
}

void globalfifo_exit(void)
{
** misc_deregister(&misc);**
}

sudo insmod ./misc_globafifo.ko后即可找到/dev/byte节点
执行命令查看生成的设施节点/dev/byte
ls /dev -al
crwxrwxrwx 1 root root 10, 57 Sep 10 06:32 byte
从打字与印刷的消息中能够看到字符设备/dev/byte主设备号为10,次设备号为57。

分类:
Linux驱动
|
评论

sscanf()境遇空格
作者
codercjg
在 18 九月 2015, 3:50 下午

sscanf从字符串按某种格式提取参数碰到空格就会甘休。
int a;
char * str = “hello 123″;
sscanf(str, “%s%d”, a);
%
s能够忽略空格从前的hello

分类:
Linux
|
评论

唯有八个字节的linux字符设备驱动
作者
codercjg
在 9 九月 2015, 3:48 下午

只有三个字节的字符设备驱动,落成阻塞和非阻塞读写、异步信号通告、select、ioctl等。
测试系统为ubuntu, 内核为linux3.2
。kernel2.3.36后ioctl变成unlock_ioctl,而且少了1个inode参数。
编排代码进程中,能够把kernel源码用source
insight建贰个工程,然后把驱动参与这几个工程,这样就能有
代码提示的意义,而且查看源码也利于,再也不用因记不住函数名和参数苦恼。
测试进度中可用tail -f /etc/var/syslog
实时翻看驱动的打字与印刷消息,而不用1次遍cat /etc/var/syslog了。
能够用lsmod查看驱动是不是已加载,用cat
/proc/devices查看设备节点是还是不是创立成功。
源码下载地址:http://pan.baidu.com/s/1t1Zt0
使得源码:

[*]  
Module unloading  
//须求支持,不然已经加载的模块不能够卸载载

include <linux/module.h>

  Device Drivers  —>

include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#include <linux/poll.h>#include <linux/device.h>

Character
devices  —>

define GLOBAL_FIFO_MAJOR 0

static int globalfifo_major = GLOBAL_FIFO_MAJOR;
/* 只有2个字节的字符设备/struct globalfifo_dev {struct cdev
cdev;unsigned char mem; /
一字节缓存/unsigned char full;
/
可写标志/struct semaphore sem;/ 信号量/wait_queue_head_t
r_wait; /
读进度等待队列头/wait_queue_head_t
w_wait;/
写进程等待队列头/struct fasync_struct async_queue;
/用以读的异步结构指针/};
struct globalfifo_dev fifodev;/文本打开函数/int
globalfifo_open(struct inode inode, struct filefilp){/将装备结构体指针赋值给文件私有数量指针/filp->private_data
= &fifodev;return 0;}
/文件释放函数/int globalfifo_release(struct inode inode, struct filefilp){/ 将文件从异步布告列表中删去 /
return 0;}
/ ioctl设备控制函数 /static int globalfifo_ioctl(struct file filp,
unsigned int cmd, unsigned long arg){struct globalfifo_dev
dev =
(struct globalfifo_dev)filp->private_data;switch(cmd){case
1:down(&dev->sem);dev->mem =
0;up(&dev->sem);printk(KERN_INFO”zero mem\n”);break;default:return
-EINVAL;}
return 0;}
/
poll函数 /static unsigned int globalfifo_poll(struct file filp,
poll_table wait){unsigned int mask = 0;struct globalfifo_dev dev =
(struct
globalfifo_dev)filp->private_data;printk(KERN_INFO”poll\n”);down(&dev->sem);
poll_wait(filp, &dev->r_wait, wait);poll_wait(filp,
&dev->w_wait, wait);if (dev->full == 1){mask |= POLLIN |
POLLRDNORM; /
标记数据可读/}else if (dev->full == 0){mask |= POLLOUT
| POLLWRNORM; /
标志数据可写/}
up(&dev->sem);return mask;}
/
globalfifo fasync函数*/static int globalfifo_fasync(int fd, struct
file filp, int mode){struct globalfifo_dev dev =
filp->private_data;printk(KERN_INFO”fasync_helper\n”);return
fasync_helper(fd, filp, mode,
&dev->async_queue);}/globalfifo读函数/static ssize_t
globalfifo_read(struct file *filp, char __user buf, size_t
count,loff_t
ppos){int ret = 1;
printk(KERN_INFO”to read %d\n”, count);struct globalfifo_dev dev =
(struct globalfifo_dev
)filp->private_data;DECLARE_WAITQUEUE(read,
current);add_wait_queue(&dev->r_wait, &read);
down(&dev->sem);if (dev->full == 0) { // 即使不行读if
(filp->f_flags & O_NONBLOCK) {// 非阻塞直接回到ret =
-EAGAIN;printk(KEEvoqueN_INFO”read EAGAIN\n”);goto out;} else
{__set_current_state(TASK_INTERRUPTIBLE);while (dev->full == 0)
{up(&dev->sem);schedule();if (signal_pending(current)) { //
阻塞时被信号打断ret = -ERESTALacrosseTSYS;printk(KESportageN_INFO”read
ERESTARTSYS\n”);goto out;}down(&dev->sem);}//
使用循环原因:可能有七个读进度被指示,实行读操作前恐怕已被其余读进程当先//所以须求重新判断可读条件}
}// 读操作if (copy_to_user(buf, &dev->mem, 1)) {ret =
-EFAULT;printk(KERN_INFO”read EFAULT\n”);goto out;}
dev->full = 0;up(&dev->sem);printk(KERN_INFO”wake_up
w\n”);wake_up_interruptible(&dev->w_wait); //
唤醒写等待队列中的进度ret = 1;
out:remove_wait_queue(&dev->r_wait,
&read);__set_current_state(TASK_RUNNING);printk(KERN_INFO”read
end\n”);
return ret;}/globalfifo写操作/static ssize_t globalfifo_write(struct
file *filp, const char __user buf,size_t count, loff_t ppos){int
ret = 1;
printk(KERN_INFO”to write %d\n”, count);struct globalfifo_dev dev =
(struct
globalfifo_dev
)filp->private_data;DECLARE_WAITQUEUE(write,
current);add_wait_queue(&dev->w_wait, &write);
down(&dev->sem);if (dev->full == 1) { //假设不可写if
(filp->f_flags & O_NONBLOCK) { //
非阻塞间接回到printk(KECRUISERN_INFO”write: O_NONBLOCK\n”);ret =
-EAGAIN;goto out;} else
{__set_current_state(TASK_INTE奥迪Q5RUPTIBLE);while (dev->full == 1)
{up(&dev->sem);schedule(); // 阻塞进度if (signal_pending(current)) {
// 阻塞时被信号打断ret = -ERESTAXC90TSYS;printk(KE路虎极光N_INFO”write:
ERESTARTSYS\n”);goto out;}down(&dev->sem);}//
使用循环原因:恐怕有四个写进度被升迁,进行写操作前恐怕已被其余写进度超过//所以供给再行判断可写条件}
}// 写操作if (copy_from_user(&dev->mem, buf, 1) ) {ret =
-EFAULT;printk(KERN_INFO”write: EFAULT\n”);goto out;}
dev->full = 1;up(&dev->sem);printk(KERN_INFO”wake_up r\n”);//
唤醒读等待队列中的进度wake_up_interruptible(&dev->r_wait);ret =
1;// 发送异步信号给读进度if
(dev->async_queue)kill_fasync(&dev->async_queue, SIGIO,
POLL_IN);
out:remove_wait_queue(&dev->w_wait,
&write);__set_current_state(TASK_RUNNING);printk(KERN_INFO”write
end\n”);
return ret;
}
/文件操作结构体/static const struct file_operations globalfifo_fops
= {.owner = THIS_MODULE,.read = globalfifo_read,.write =
globalfifo_write,.unlocked_ioctl = globalfifo_ioctl,.poll =
globalfifo_poll,.open = globalfifo_open,.release =
globalfifo_release,.fasync = globalfifo_fasync,};struct class
*hello_class;int globalfifo_init(void){int ret;dev_t devno =
MKDEV(globalfifo_major, 0);if (globalfifo_major) {ret =
register_chrdev_region(devno, 1, “globalfifo”);} else {//
动态分配主设备号ret = alloc_chrdev_region(&devno, 0, 1,
“globalfifo”);globalfifo_major = MAJOR(devno);}if (ret < 0)return
ret;memset(&fifodev, 0, sizeof(struct globalfifo_dev));
cdev_init(&fifodev.cdev, &globalfifo_fops);fifodev.cdev.owner =
THIS_MODULE;cdev_add(&fifodev.cdev, devno, 1);sema_init(&fifodev.sem,
1);init_waitqueue_head(&fifodev.r_wait);init_waitqueue_head(&fifodev.w_wait);
// 创造设备节点/dev/bytehello_class = class_create(THIS_MODULE,
“fifo_class”);device_create(hello_class, NULL,
MKDEV(globalfifo_major, 0), NULL,
“byte”);printk(KERN_INFO”fifo_init\n”);return 0; //
记得要有再次回到值,不然insmod的时候会唤醒出错}
void globalfifo_exit(void){
// 删除设备节点/dev/bytedevice_destroy(hello_class,
MKDEV(globalfifo_major, 0));class_destroy(hello_class);
cdev_del(&fifodev.cdev);unregister_chrdev_region(MKDEV(globalfifo_major,
0), 1);printk(KERN_INFO”fifo_exit\n”);}
MODULE_AUTHOR(“codercjg”);MODULE_LICENSE(“Dual BSD/GPL”);
module_param(globalfifo_major, int, S_IRUGO);
module_init(globalfifo_init);module_exit(globalfifo_exit);
编写翻译驱动Makefile:
obj-m := globalfifo.o
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
.PHONY: clean
clean:
rm -rf *.o *.ko
加载驱动脚本:

<M>
FL2440 Hello Driver
 //刚才添加的Kconfig选项,那里编写翻译为模块

!/bin/bash

sudo insmod ./globalfifo.ko
sudo chmod 777 /dev/byte
卸载驱动脚本:

5,make之后,下载内核与文件系统,挂在hello.ko模块

!/bin/bash

sudo rm /dev/byte
sudo rmmod globalfifo
阻塞写:

Copyright (C) 2014
zhouguangfeng<zhouguangfeng@gmail.com>
dm9000 dm9000 eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
zhouxiaoxing login: root
>: ls
apps     data     etc      info     lib      mnt      root     sys    
 usr
bin      dev      hello    init     linuxrc  proc     sbin     tmp    
 var
>: ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=64 time=2.592 ms
64 bytes from 192.168.1.1: seq=1 ttl=64 time=0.685 ms
64 bytes from 192.168.1.1: seq=2 ttl=64 time=0.658 ms

include <unistd.h>

— 192.168.1.1 ping statistics —
9 packets transmitted, 9 packets received, 0% packet loss
round-trip min/avg/max = 0.658/0.896/2.592 ms

include <sys/types.h>

>: tftp -gr
hello.ko 192.168.1.3
hello.ko             100%
|*******************************|  2365  
0:00:00 ETA
>: ls
apps      dev       hello.ko  lib       proc      sys       var
bin       etc       info      linuxrc   root      tmp
data      hello     init      mnt       sbin      usr

include <sys/stat.h>

>: insmod
hello.ko 

include <fcntl.h>

Hello world

include <stdio.h>

int main(int argc, char **argv)
{
int fd;
ssize_t size;
char ch;
if(argc<2){
printf(“usage: write 1\n”);
return 1;
}
ch = argv[1][0];
fd = open(“/dev/byte”, O_WRONLY);
size = write(fd, &ch, 1);
if(size > 0){
printf(“%c\n”, ch);
}else{
printf(“err\n”);
}
close(fd);
return 0;
}
阻塞读:

>: rmmod hello 

include <unistd.h>

Goodbye
world

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <stdio.h>

int main(void)
{
int fd;
ssize_t size;
char buf[2];
fd = open(“/dev/byte”, O_RDONLY);
size = read(fd, buf, 1);
if(size > 0){
printf(“%c\n”, buf[0]);
}else{
printf(“err\n”);
}
close(fd);
return 0;
}
异步信号读:

include <unistd.h>

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <stdio.h>

include <signal.h>

include <sys/ioctl.h>

int fd;
char ch;
void io_handler(int sigio)
{
size_t size;
size = read(fd, &ch, 1);
if(size > 0){
printf(“%c\n”, ch);
}else{
printf(“err\n”);
}
}
int main(void)
{
int flag;
signal(SIGIO, io_handler);
fd = open(“/dev/byte”, O_RDONLY);
if(ioctl(fd, 1)<0){
perror(“ioctl”);
return 1;
}
fcntl(fd, F_SETOWN, getpid());
flag = fcntl(fd, F_GETFL);
flag |= FASYNC;
fcntl(fd, F_SETFL, flag);
while(ch != ‘q’);
close(fd);
return 0;
}
select读:

include <sys/types.h>

include <sys/stat.h>

include <fcntl.h>

include <stdio.h>

include <sys/time.h>

int main(void)
{
fd_set inset;
struct timeval timeout;
int ret;
int fd;
ssize_t size;
char ch;
fd = open(“/dev/byte”, O_RDONLY);
while(1)
{
timeout.tv_sec = 2;
timeout.tv_usec = 0;
FD_ZERO(&inset);
FD_SET(fd, &inset);
ret = select(fd+1, &inset, NULL, NULL, NULL);
if(ret>0 && FD_ISSET(fd, &inset))
{
read(fd, &ch, 1);
printf(“%c\n”, ch);
if(ch == ‘q’)
break;
} else if(ret==0)
{
printf(“time out\n”);
}else{
perror(“select”);
}
}
close(fd);
return 0;
}

分类:
Linux驱动
|
评论

实时打字与印刷syslog音信
作者
codercjg
在 8 九月 2015, 5:20 下午

tail -f /var/log/syslog

分类:
Linux
|
评论

相关文章