ldd3笔记

来源:互联网 发布:网络女强与传统女强 编辑:程序博客网 时间:2024/04/30 13:09

 module_param(variable, type, perm);    //参数格式

dev_t :12 位用作主编号, 20 位用作次编号.   MKDEV(int major, int minor);  MAJOR(dev_t dev);  MINOR(dev_t dev);

静态:int register_chrdev_region(dev_t first, unsigned int count, char *name);  , name 是会出现在 /proc/devices 和 sysfs 中.

动态:int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);

file_operation 结构是一个字符驱动如何建立这个连接.       注:对于正常的编译,__user 没有效果,但是它可被外部检查软件使用来找出对用户空间地址的错误使用.

struct file, 定义于 <linux/fs.h>, . 注意 file 与用户空间程序的FILE 指针没有任何关系,它由内核在 open 时创建,成员:struct file_operations*f_op; void *private_data;等

inode 结构由内核在内部用来表示文件.  成员:dev_t   i_rdev;   structcdev *i_cdev;

struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;

void cdev_init(struct cdev *cdev, struct file_operations *fops);

int cdev_add(struct cdev *dev, dev_t num, unsigned int count);

例:

struct scull_dev {
//自己定义的变量:

........

struct cdev cdev; /* Char device structure */
};

int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);

 

int (*open)(struct inode *inode, struct file *filp);

inode 参数的 i_cdev 成员里面包含我们之前建立的 cdev 结构,container_of(pointer, container_type, container_field);
例子:struct scull_dev *dev; /* device information */        dev = container_of(inode->i_cdev, struct scull_dev, cdev);

 

是如果你不需要检查用户空间指针, 你可以调用 __copy_to_user 和 __copy_from_user 来代替copy_to_user 

更有效地(小数据项,)  int access_ok(int type, const void *addr, unsigned long size);

如果 klogd和 syslogd 都在系统中运行, 内核消息被追加到 /var/log/messages

strace 命令时一个有力工具, 显示所有的用户空间程序发出的系统调用

互斥锁:  DECLARE_MUTEX(name);   //初始化1       DECLARE_MUTEX_LOCKED(name);   //初始化0

void down(struct semaphore *sem);      int down_interruptible(struct semaphore *sem);  //可中断:允许在等待旗标的用户空间进程被用户中断

   int down_trylock(struct semaphore *sem);  //旗标在调用时不可用, down_trylock立刻返回一个非零

completion 是任务使用的一个轻量级机制: 允许一个线程告诉另一个线程工作已经完成  struct completion my_completion;  init_completion(&my_completion);
等待 completion 是一个简单事来调用:   void wait_for_completion(struct completion *c);   //注意这个函数进行一个不可打断的等待      completion 事件可能通过调用下列之一来发出:  void complete(struct completion *c);         void complete_all(struct completion *c);

自旋锁可用在不能睡眠的代码中, 例如中断处理,  自旋锁提供了比旗标更高的性能.    void spin_lock_init(spinlock_t *lock);

void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);  //?
void spin_lock_irq(spinlock_t *lock);
void spin_lock_bh(spinlock_t *lock)

避免加锁:原子变量(提高效率)   atomic_set,atomic_read、atomic_read、、

seqlock:一对新机制打算来提供快速地, 无锁地存取一个共享资源. 当发生这样的冲突时, 重试它们的存取.

阻塞 I/O  持有锁时不能睡眠. 如果你已关闭中断时也不能睡眠.  睡眠:一个等待队列,,wait_event_interruptible

互斥等待:只有一个被唤醒的进程时( WQ_FLAG_EXCLUSEVE 标志, 添加队列的尾部. 没有: 添加到开始;在唤醒第一个有 WQ_FLAG_EXCLUSIVE 标志的进程后停止)

非阻塞 I/O : poll, select, 和 epoll 系

jiffies:每次发生一个时钟中断, 一个内核计数器的值递增. unsigned long  stamp_1 =jiffies+HZ; /*1 second in the future */       jiffies比较函数:time_before

高精度:cycles_t get_cycles(void);

超时响应wait_event_interruptible_timeout(wait_queue_head_t q, condition, long timeout);  或者schedule_timeout 例子:set_current_state(TASK_INTERRUPTIBLE);                 schedule_timeout (delay);

短延时:函数 ndelay, udelay, 以及 mdelay  执行指定的纳秒数, 微秒数或者毫秒,3 个延时函数是忙等待

定时器 API:  init_timer(struct timer_list *timer);    add_timer   mod_timer

内存:kmem_cache_create     kmem_cache_alloc

一个内存池真实地只是一类后备缓存, 它尽力一直保持一个空闲内存列表给紧急时使用.  mempool_create    mempool_alloc_slab 和 mempool_free_slab)

分配大块的内存:get_zeroed_page

每-CPU 的变量:DEFINE_PER_CPU(type, name);         get_cpu_var 宏来存取当前处理器的给定变量拷贝

硬件io:void barrier(void)   rmb   wmb  mb  rmb( read memory barrier) 保证任何出现于屏障前的读在执行任何后续读之前完成,避免系统在缓存时引起故障

I/O 端口分配: struct resource *request_region(unsigned long first, unsigned long n, const char *name);      check_region  检查端口是否可用

如果主机平台没有 ioperm 和 iopl 系统调用, 用户空间仍然可以存取 I/O 端口, 通过使用 /dev/port 设备文件

字串操作:传送一系列字节,insb,insw,insl,可能这些函数只在X86机器上有