日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux轮询脚本,linux驱动的等待队列(阻塞操作)和轮询(poll),缓冲区笔记

發(fā)布時間:2024/9/3 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux轮询脚本,linux驱动的等待队列(阻塞操作)和轮询(poll),缓冲区笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

覺得還是貼代碼最直接,以后要用的時候也方便參考。

先是相應(yīng)驅(qū)動的詳細(xì)代碼:

/* linux/drivers/char/sep4020_char/sep4020_fifo.c

*

* Copyright (c) 2009 leeming

*

* sep4020 fifo driver.

*

* Changelog:

*?12-Aug-2009 leeming?Initial version

*

* This program is free software; you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation; either version 2 of the License, or

* (at your option) any later version.

*/

#include #include #include #include #include #include #include #include #include #include #include #include #include

#include #include #include #include #include

#define FIFO_MAJOR 252????????? //主設(shè)備號

#define MAX_FIFO_BUF 16???????? //按鍵緩沖區(qū)的大小

struct fifodev

{

unsigned char buf[MAX_FIFO_BUF];?? //按鍵緩沖區(qū)

unsigned int current_len;

wait_queue_head_t r_wait;??????????? //讀等待隊列

wait_queue_head_t w_wait;??????????? //寫等待隊列

struct cdev cdev;

} ;

struct fifodev *fifo_dev;???? //鍵盤結(jié)構(gòu)體

//返回讀到的字節(jié)數(shù)

static ssize_t sep4020_fifo_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)

{

int ret;

// 第二個參數(shù)condition必須滿足,否則阻塞

wait_event_interruptible(fifo_dev->r_wait, fifo_dev->current_len != 0);

if(size > fifo_dev->current_len)

size = fifo_dev->current_len;

if(copy_to_user(buf, fifo_dev->buf, size))

{

ret = -EFAULT;

goto out;

}

else

{

memcpy(fifo_dev->buf, fifo_dev->buf+size, fifo_dev->current_len-size);

fifo_dev->current_len = fifo_dev->current_len - size;

wake_up_interruptible(&fifo_dev->w_wait);

ret = size;

}

out:

return ret;

}

//返回寫入的字節(jié)數(shù)

static ssize_t sep4020_fifo_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)

{

int ret;

wait_event_interruptible(fifo_dev->r_wait, fifo_dev->current_len != MAX_FIFO_BUF);

if(size > (MAX_FIFO_BUF-fifo_dev->current_len))

{

size = MAX_FIFO_BUF-fifo_dev->current_len;

}

if(copy_from_user(fifo_dev->buf+fifo_dev->current_len, buf, size))

{

ret = -EFAULT;

goto out;

}

else

{

fifo_dev->current_len += size;

ret = size;

}

wake_up_interruptible(&fifo_dev->r_wait);

out:

return ret;

}

//在使用echo或者cat的時候都會調(diào)用open函數(shù)

static int sep4020_fifo_open(struct inode *inode, struct file *filp)

{

//memset(fifo_dev->buf, 0, MAX_FIFO_BUF);

//fifo_dev->current_len = 0;

return 0;

}

static int sep4020_fifo_release(struct inode *inode, struct file *filp)

{

return 0;

}

/*

#define POLLIN???0x0001 ?//有數(shù)據(jù)可以讀入,read不會阻塞,注意:select的請情況下,即使到EOF也是ready的.

#define POLLPRI??0x0002?//緊急數(shù)據(jù),比如TCP,或者packet模式的peseudo-terminal發(fā)現(xiàn)slave的狀態(tài)有變化.

#define POLLOUT??0x0004?//寫入不會阻塞.

#define POLLERR??0x0008?//輸出出錯

#define POLLHUP??0x0010?//Hang up (output only).

#define POLLNVAL??0x0020?//Invalid request: fd not open (output only).

The rest seem to be more-or-less nonstandard. Check them!

#define POLLRDNORM?0x0040?//POLLIN.

#define POLLRDBAND?0x0080?//高優(yōu)先級的數(shù)據(jù)read for read (generally unused on Linux).

#define POLLWRNORM?0x0100?//Equivalent to POLLOUT.

#define POLLWRBAND?0x0200?//Priority data may be written.

#define POLLMSG??0x0400

#define POLLREMOVE?0x1000

*/

static unsigned int sep4020_fifo_poll(struct file *filp, poll_table *wait)

{

unsigned int mask = 0;

//加入這兩句話是為了在讀寫狀態(tài)發(fā)生變化的時候,通知核心層,讓核心層重新調(diào)用poll函數(shù)查詢信息。也就是說這兩句只會在select阻塞的時候用到

//當(dāng)利用select函數(shù)發(fā)現(xiàn)既不能讀又不能寫時,select函數(shù)會阻塞,但是此時的阻塞并不是輪詢,而是睡眠,通過下面兩個隊列發(fā)生變化時通知select

poll_wait(filp, &fifo_dev->r_wait, wait);

poll_wait(filp, &fifo_dev->w_wait, wait);

if(fifo_dev->current_len != 0)

{

mask |= POLLIN | POLLRDNORM;//可讀,同時寫上POLLRDNORM

}

if(fifo_dev->current_len != MAX_FIFO_BUF)

{

mask |= POLLOUT | POLLWRNORM;//可寫,同時寫上POLLWRNORM

}

return mask;

}

static struct file_operations sep4020_fifo_fops =

{

.owner = THIS_MODULE,

.read? = sep4020_fifo_read,

.write = sep4020_fifo_write,

.poll? = sep4020_fifo_poll,

.open? = sep4020_fifo_open,

.release = sep4020_fifo_release,

};

static int __init sep4020_fifo_init(void)

{

int err,result;

dev_t devno;

devno = MKDEV(FIFO_MAJOR, 0);

result = register_chrdev_region(devno, 1, "sep4020_fifo");?? //向系統(tǒng)靜態(tài)申請設(shè)備號

if (result < 0)

{

return result;

}

fifo_dev = kmalloc(sizeof(struct fifodev), GFP_KERNEL);

if (fifo_dev == NULL)

{

result = -ENOMEM;

unregister_chrdev_region(devno, 1);

return result;

}

memset(fifo_dev,0,sizeof(struct fifodev));? //初始化

cdev_init(&fifo_dev->cdev, &sep4020_fifo_fops);

fifo_dev->cdev.owner = THIS_MODULE;

//初始化等待對列

init_waitqueue_head(&fifo_dev->r_wait);

init_waitqueue_head(&fifo_dev->w_wait);

//向系統(tǒng)注冊該字符設(shè)備

err = cdev_add(&fifo_dev->cdev, devno, 1);

if (err)

{

printk("fifo adding err\r\n");

unregister_chrdev_region(devno,1);

kfree(fifo_dev);

return err;

}

return 0;

}

static void __exit sep4020_fifo_exit(void)

{

cdev_del(&fifo_dev->cdev);

kfree(fifo_dev);

unregister_chrdev_region(MKDEV(FIFO_MAJOR, 0), 1);

}

module_init(sep4020_fifo_init);

module_exit(sep4020_fifo_exit);

MODULE_AUTHOR("Leeming Zhang");

MODULE_LICENSE("GPL");

/*****************************************************************************************************************/

接下來是相應(yīng)的應(yīng)用程序:

#include #include #include #include

int main(int argc, char **argv)

{

int fd;

char buf[16];

fd_set rfds,wfds;?//讀寫描述符集合

unsigned char w_buf[7] = {'a','b','c','d','e','f','g'};

//open的標(biāo)志位有:O_RDONLY O_WRONLY O_RDWR O_NONBLOCK O_NDELAY O_SYNC O_NOCTY

fd = open("/dev/fifo",O_RDWR);

if(fd == -1)

{

printf("wrong\r\n");

exit(-1);

}

while(1)

{

//初始化文件描述符集合

//清零

FD_ZERO(&rfds);

FD_ZERO(&wfds);

//將文件描述符加入文件描述符集合中,利用函數(shù)FD_CLR(int fd,fd_set *set)將一個文件描述符從文件描述符集中清除

FD_SET(fd, &rfds);

FD_SET(fd, &wfds);

//函數(shù)原型:int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

//readfds writefds exceptfds分別是被select監(jiān)視的讀,寫和異常處理的文件描述符集合,numfds是需要檢查的文件描述符加1。

select(fd+1, &rfds, &wfds, NULL, NULL);

//判斷是否被置位,通過select函數(shù)調(diào)用驅(qū)動poll函數(shù)的返回值,來判斷是否可讀,還是可寫,還是又能讀又能寫;當(dāng)然如果驅(qū)動又不能讀又不能寫,在select那兒會阻塞,直到能讀或者能寫為止

if(FD_ISSET(fd, &rfds))

{

printf("Poll monitor: can be read\n");

}

if(FD_ISSET(fd, &wfds))

{

printf("Poll monitor: can be written\n");

}

}

return 0;

}

總結(jié)

以上是生活随笔為你收集整理的linux轮询脚本,linux驱动的等待队列(阻塞操作)和轮询(poll),缓冲区笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。