国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Linux操作系統內核和設備文件對話

系統 Linux
設備文件是用來代表物理設備的。多數物理設備是用來進行輸出或輸入的,所以必須由某種機制使得內核中的設備驅動從進程中得到輸出送給設備。

設備文件是用來代表物理設備的。多數物理設備是用來進行輸出或輸入的,所以必須由某種機制使得內核中的設備驅動從進程中得到輸出送給設備。這可以通過打開輸出設備文件并且寫入做到,就想寫入一個普通文件。在下面的例子里,這由device_write實現。

這不是總能奏效的。設想你與一個連向modem的串口(技是你有一個內貓,從CPU看來它也是作為一個串口實現,所以你不需要認為這個設想太困難)。最自然要做的事情就是使用設備文件把內容寫到modem上(無論用modem命令還是電話線)或者從modem讀信息(同樣可以從modem命令回答或者通過電話線)。但是這留下的問題是當你需要和串口本身對話的時候需要怎樣做?比如發送數據發送和接收的速率。

回答是Unix使用一個叫做ioctl(input output control的簡寫)的特殊函數。每個設備都有自己的ioctl命令,這個命令可以是ioctl讀的,也可以是寫的,也可以是兩者都是或都不是。Ioctl函數由三個參數調用:適當設備的描述子,ioctl數,和一個長整型參數,可以賦予一個角色用來傳遞任何東西。

Ioctl數對設備主碼、ioctl類型、編碼、和參數的類型進行編碼。Ioctl數通常在頭文件由一個宏調用(_IO,_IOR,_IOW或_IOWR——決定于類型)。這個頭文件必須包含在使用ioctl(所以它們可以產生正確的ioctl's)程序和內核模塊(所以它可以理解)中。在下面的例子里,這個頭文件是chardev.h,使用它的程序是ioctl.c。

如果你希望在你自己的內核模塊中使用ioctl's,最好去接受一分正式的ioctl職位,這樣你就可以得到別人的ioctl's,或者他們得到你,你就可以知道哪里出了錯誤。如果想得到更多的信息,到'documentation/ioctl-number.txt'中查看內核源文件樹。

ex chardev.c

/* chardev.c

*

* Create an input/output character device

*/

/* Copyright (C) 1998-99 by Ori Pomerantz */

/* The necessary header files */

/* Standard in kernel modules */

#include /* Were doing kernel work */

#include /* Specifically, a module */

/* Deal with CONFIG_MODVERSIONS */

#if CONFIG_MODVERSIONS==1

#define MODVERSIONS

#include

#endif

/* For character devices */

/* The character device definitions are here */

#include

/* A wrapper which does next to nothing at

* at present, but may help for compatibility

* with future versions of Linux */

#include

/* Our own ioctl numbers */

#include "chardev.h"

/* In 2.2.3 /usr/include/linux/version.h includes a

* macro for this, but 2.0.35 doesnt - so I add it

* here if necessary. */

#ifndef KERNEL_VERSION

#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))

#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

#include /* for get_user and put_user */

#endif

#define SUCCESS 0

#p#

/* Device Declarations ******************************** */

/* The name for our device, as it will appear in

* /proc/devices */

#define DEVICE_NAME "char_dev"

/* The maximum length of the message for the device */

#define BUF_LEN 80

/* Is the device open right now? Used to prevent

* concurent access into the same device */

static int Device_Open = 0;

/* The message the device will give when asked */

static char Message[BUF_LEN];

/* How far did the process reading the message get?

* Useful if the message is larger than the size of the

* buffer we get to fill in device_read. */

static char *Message_Ptr;

/* This function is called whenever a process attempts

* to open the device file */

static int device_open(struct inode *inode,

struct file *file)

{

#ifdef DEBUG

printk ("device_open(%p)\n", file);

#endif

/* We dont want to talk to two processes at the

* same time */

if (Device_Open)

return -EBUSY;

/* If this was a process, we would have had to be

* more careful here, because one process might have

* checked Device_Open right before the other one

* tried to increment it. However, were in the

* kernel, so were protected against context switches.

*

* This is NOT the right attitude to take, because we

* might be running on an SMP box, but well deal with

* SMP in a later chapter.

*/

Device_Open++;

/* Initialize the message */

Message_Ptr = Message;

MOD_INC_USE_COUNT;

return SUCCESS;

}

/* This function is called when a process closes the

* device file. It doesnt have a return value because

* it cannot fail. Regardless of what else happens, you

* should always be able to close a device (in 2.0, a 2.2

* device file could be impossible to close). */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

static int device_release(struct inode *inode,

struct file *file)

#else

static void device_release(struct inode *inode,

struct file *file)

#endif

{

#ifdef DEBUG

printk ("device_release(%p,%p)\n", inode, file);

#endif

/* Were now ready for our next caller */

Device_Open --;

MOD_DEC_USE_COUNT;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

return 0;

#endif

}

/* This function is called whenever a process which

* has already opened the device file attempts to

* read from it. */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

static ssize_t device_read(

struct file *file,

char *buffer, /* The buffer to fill with the data */

size_t length, /* The length of the buffer */

loff_t *offset) /* offset to the file */

#else

static int device_read(

struct inode *inode,

struct file *file,

char *buffer, /* The buffer to fill with the data */

int length) /* The length of the buffer

* (mustnt write beyond that!) */

#endif

#p#{

/* Number of bytes actually written to the buffer */

int bytes_read = 0;

#ifdef DEBUG

printk("device_read(%p,%p,%d)\n",

file, buffer, length);

#endif

/* If were at the end of the message, return 0

* (which signifies end of file) */

if (*Message_Ptr == 0)

return 0;

/* Actually put the data into the buffer */

while (length && *Message_Ptr) {

/* Because the buffer is in the user data segment,

* not the kernel data segment, assignment wouldnt

* work. Instead, we have to use put_user which

* copies data from the kernel data segment to the

* user data segment. */

put_user(*(Message_Ptr++), buffer++);

length --;

bytes_read ++;

}

#ifdef DEBUG

printk ("Read %d bytes, %d left\n",

bytes_read, length);

#endif

/* Read functions are supposed to return the number

* of bytes actually inserted into the buffer */

return bytes_read;

}

/* This function is called when somebody tries to

* write into our device file. */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

static ssize_t device_write(struct file *file,

const char *buffer,

size_t length,

loff_t *offset)

#else

static int device_write(struct inode *inode,

struct file *file,

const char *buffer,

int length)

#endif

{

int i;

#ifdef DEBUG

printk ("device_write(%p,%s,%d)",

file, buffer, length);

#endif

for(i=0; i

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

get_user(Message, buffer+i);

#else

Message = get_user(buffer+i);

#endif

Message_Ptr = Message;

/* Again, return the number of input characters used */

return i;

}

/* This function is called whenever a process tries to

* do an ioctl on our device file. We get two extra

* parameters (additional to the inode and file

* structures, which all device functions get): the number

* of the ioctl called and the parameter given to the

* ioctl function.

*

* If the ioctl is write or read/write (meaning output

* is returned to the calling process), the ioctl call

* returns the output of this function.

*/

int device_ioctl(

struct inode *inode,

struct file *file,

unsigned int ioctl_num,/* The number of the ioctl */

unsigned long ioctl_param) /* The parameter to it */

#p#{

int i;

char *temp;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

char ch;

#endif

/* Switch according to the ioctl called */

switch (ioctl_num) {

case IOCTL_SET_MSG:

/* Receive a pointer to a message (in user space)

* and set that to be the devices message. */

/* Get the parameter given to ioctl by the process */

temp = (char *) ioctl_param;

/* Find the length of the message */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

get_user(ch, temp);

for (i=0; ch && ibr temp++) i++,> get_user(ch, temp);

#else

for (i=0; get_user(temp) && ibr temp++) i++,> ;

#endif

/* Dont reinvent the wheel - call device_write */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

device_write(file, (char *) ioctl_param, i, 0);

#else

device_write(inode, file, (char *) ioctl_param, i);

#endif

break;

case IOCTL_GET_MSG:

/* Give the current message to the calling

* process - the parameter we got is a pointer,

* fill it. */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

i = device_read(file, (char *) ioctl_param, 99, 0);

#else

i = device_read(inode, file, (char *) ioctl_param,

99);

#endif

/* Warning - we assume here the buffer length is

* 100. If its less than that we might overflow

* the buffer, causing the process to core dump.

*

* The reason we only allow up to 99 characters is

* that the NULL which terminates the string also

* needs room. */

/* Put a zero at the end of the buffer, so it

* will be properly terminated */

put_user(\, (char *) ioctl_param+i);

break;

case IOCTL_GET_NTH_BYTE:

/* This ioctl is both input (ioctl_param) and

* output (the return value of this function) */

return Message[ioctl_param];

break;

}

return SUCCESS;

}

#p#/* Module Declarations *************************** */

/* This structure will hold the functions to be called

* when a process does something to the device we

* created. Since a pointer to this structure is kept in

* the devices table, it cant be local to

* init_module. NULL is for unimplemented functions. */

struct file_operations Fops = {

NULL, /* seek */

device_read,

device_write,

NULL, /* readdir */

NULL, /* select */

device_ioctl, /* ioctl */

NULL, /* mmap */

device_open,

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

NULL, /* flush */

#endif

device_release /* a.k.a. close */

};

/* Initialize the module - Register the character device */

int init_module()

{

int ret_val;

/* Register the character device (atleast try) */

ret_val = module_register_chrdev(MAJOR_NUM,

DEVICE_NAME,

&Fops);

/* Negative values signify an error */

if (ret_val < 0) {

printk ("%s failed with %d\n",

"Sorry, registering the character device ",

ret_val);

return ret_val;

}

printk ("%s The major device number is %d.\n",

"Registeration is a success",

MAJOR_NUM);

printk ("If you want to talk to the device driver,\n");

printk ("youll have to create a device file. \n");

printk ("We suggest you use:\n");

printk ("mknod %s c %d 0\n", DEVICE_FILE_NAME,

MAJOR_NUM);

printk ("The device file name is important, because\n");

printk ("the ioctl program assumes thats the\n");

printk ("file youll use.\n");

return 0;

}

/* Cleanup - unregister the appropriate file from /proc */

void cleanup_module()

{

int ret;

/* Unregister the device */

ret = module_unregister_chrdev(MAJOR_NUM, DEVICE_NAME);

/* If theres an error, report it */

if (ret < 0)

printk("Error in module_unregister_chrdev: %d\n", ret);

}

ex chardev.h

/* chardev.h - the header file with the ioctl definitions.

*

* The declarations here have to be in a header file,

* because they need to be known both to the kernel

* module (in chardev.c) and the process calling ioctl

* (ioctl.c)

*/

#ifndef CHARDEV_H

#define CHARDEV_H

#include

/* The major device number. We cant rely on dynamic

* registration any more, because ioctls need to know

* it. */

#define MAJOR_NUM 100

/* Set the message of the device driver */

#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)

/* _IOR means that were creating an ioctl command

* number for passing information from a user process

* to the kernel module.

#p#*

* The first arguments, MAJOR_NUM, is the major device

* number were using.

*

* The second argument is the number of the command

* (there could be several with different meanings).

*

* The third argument is the type we want to get from

* the process to the kernel.

*/

/* Get the message of the device driver */

#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)

/* This IOCTL is used for output, to get the message

* of the device driver. However, we still need the

* buffer to place the message in to be input,

* as it is allocated by the process.

*/

/* Get the nth byte of the message */

#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)

/* The IOCTL is used for both input and output. It

* receives from the user a number, n, and returns

* Message[n]. */

/* The name of the device file */

#define DEVICE_FILE_NAME "char_dev"

#endif

ex ioctl.c

/* ioctl.c - the process to use ioctls to control the

* kernel module

*

* Until now we could have used cat for input and

* output. But now we need to do ioctls, which require

* writing our own process.

*/

/* Copyright (C) 1998 by Ori Pomerantz */

/* device specifics, such as ioctl numbers and the

* major device file. */

#include "chardev.h"

#include /* open */

#include /* exit */

#include /* ioctl */

/* Functions for the ioctl calls */

ioctl_set_msg(int file_desc, char *message)

{

int ret_val;

ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

if (ret_val < 0) {

printf ("ioctl_set_msg failed:%d\n", ret_val);

exit(-1);

}

}

ioctl_get_msg(int file_desc)

{

int ret_val;

char message[100];

/* Warning - this is dangerous because we dont tell

* the kernel how far its allowed to write, so it

* might overflow the buffer. In a real production

* program, we would have used two ioctls - one to tell

* the kernel the buffer length and another to give

* it the buffer to fill

*/

ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);

if (ret_val < 0) {

printf ("ioctl_get_msg failed:%d\n", ret_val);

exit(-1);

}

printf("get_msg message:%s\n", message);

}

ioctl_get_nth_byte(int file_desc)

{

int i;

char c;

printf("get_nth_byte message:");

i = 0;

while (c != 0) {

c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);

if (c < 0) {

printf(

"ioctl_get_nth_byte failed at the %dth byte:\n", i);

exit(-1);

}

putchar(c);

}

putchar(\n);

}

/* Main - Call the ioctl functions */

main()

{

int file_desc, ret_val;

char *msg = "Message passed by ioctl\n";

file_desc = open(DEVICE_FILE_NAME, 0);

if (file_desc < 0) {

printf ("Cant open device file: %s\n",

DEVICE_FILE_NAME);

exit(-1);

}

ioctl_get_nth_byte(file_desc);

ioctl_get_msg(file_desc);

ioctl_set_msg(file_desc, msg);

close(file_desc);

}

【編輯推薦】

  1. 黑客再爆Linux內核高危漏洞 可以攻擊所有Linux系統
  2. Linux內核完全剖析---數學協處理器
  3. Linux內核完全剖析---math_emulate.c程序
責任編輯:趙寧寧 來源: chinaitlab
相關推薦

2011-01-14 16:23:46

Linux內核

2009-06-19 20:32:00

Linux

2009-12-22 12:14:11

Linux內核

2009-12-17 18:19:12

Linux操作系統

2011-01-04 18:15:21

2020-12-28 08:51:06

操作系統微內核Dubbo

2009-02-17 16:07:29

Linux操作系統內核啟動參數

2017-08-24 11:00:56

Linux用戶空間內核空間

2010-04-29 14:08:38

Unix操作系統

2019-06-14 08:24:16

塊設備Linux操作系統

2009-09-01 09:20:24

Linux操作系統聲音設備編程實例

2010-04-22 15:27:40

Aix操作系統

2009-12-09 17:25:19

Linux操作系統

2009-12-10 14:27:07

Linux操作系統

2020-05-08 16:39:01

內存系統架構Linux

2011-01-14 16:01:27

2009-06-21 13:50:03

Linux隱藏文件

2011-01-14 16:51:44

Linux內核

2009-12-02 14:50:28

操作系統

2010-04-22 15:53:46

Aix操作系統設備
點贊
收藏

51CTO技術棧公眾號

成人看的视频| 在线成人动漫| 亚洲天堂导航| 亚洲免费观看高清完整版在线| 2014国产精品| 中文字幕一区久| 一区二区在线观看免费视频播放| 九九热爱视频精品视频| 精品免费在线观看| 日韩女优毛片在线| 午夜欧美福利视频| 欧美日韩一区二区高清| 欧美高清视频在线观看| 91精品黄色| 精品久久亚洲| 日韩免费高清视频| 影音先锋可以看的网站| 99视频一区二区三区| 免费日韩av电影| 日韩高清三区| 国产亚洲欧洲高清| 黄毛片在线观看| 日韩欧美不卡一区| 国产精品自拍视频| 欧美三级伦理在线| 91成人精品网站| 一区二区三区在线资源| 中文字幕免费精品一区| 中文不卡1区2区3区| 欧美精品一区二| 日韩黄色影院| 日韩免费观看高清完整版在线观看| 国产福利在线观看| 精品视频在线免费看| 韩日视频在线| 欧美一区二区三级| 蜜桃在线视频| 久久久国产精彩视频美女艺术照福利| 国产激情在线播放| 国产一区二区日韩| 视频一区日韩精品| 中文字幕欧美国产| 国产wwwxx| 最新日韩在线视频| 麻豆电影在线观看| 欧美一卡2卡三卡4卡5免费| 日本动漫同人动漫在线观看| 91原创在线视频| 嫩草嫩草嫩草嫩草| 日韩精品在线观| 国产伦理一区| 日本高清视频在线观看| 国产无套精品一区二区| 91精品在线观看入口| 国产手机视频一区二区| 国产精品一区二区三区四区色| 97久久精品午夜一区二区| 日本久久精品电影| 欧美一区高清| 欧美一区二区三区| 亚洲综合色在线观看| 欧美日韩午夜影院| 日韩视频一区二区三区在线播放免费观看| 黄色网免费看| 亚洲自拍偷拍在线| 一本色道久久综合亚洲91| 国产精品三级| 午夜国产在线| 久久久久久国产精品免费免费| 91精品办公室少妇高潮对白| 在线看片不卡| 国产裸舞福利在线视频合集| 精品国产综合久久| 国产亚洲精品91在线| 蜜桃久久久久久| 欧美 日韩 国产 高清| 中文字幕av日韩| 国产精品国产三级国产有无不卡 | 中文字幕视频精品一区二区三区| 久久香蕉视频网站| 国产视频在线一区二区| 国产欧美精品一区aⅴ影院| 国产一区二区在线观| 国产精品久久久久永久免费看| 国产97在线亚洲| 日本电影亚洲天堂一区| 精品一区二区精品| 亚洲日本va午夜在线电影| 黄页网站视频在线观看| 超碰97在线人人| 中文字幕av一区中文字幕天堂| 久久久久国产一区二区三区四区| 亚洲欧洲av| 欧美电影h版| 免费网站黄在线观看| 在线影院av| http://嫩草影院| 国产 日韩 欧美在线| 日韩欧美亚洲v片| 亚洲精品久久7777777| 毛片av一区二区| 韩国精品视频在线观看| 中文字幕成人在线视频| 日韩一区二区欧美| 日韩av在线发布| 欧洲精品二区| 一区二区在线不卡| 色一情一乱一区二区| 亚洲精品视频观看| 午夜在线一区二区| 激情av综合| 久草免费在线视频| 中文字幕 91| 在线免费一区| 欧美一区二区三区精品电影| aaaa欧美| 一级在线观看| 福利视频免费在线观看| 日本亚洲欧洲色α| 日韩高清免费在线| 色偷偷成人一区二区三区91| 国产福利一区二区| 这里只有精品在线| 欧美电影在线观看网站| 国产毛片av在线| 四虎4hu新地址入口2023| 欧美大陆一区二区| www.黄色网址.com| 久久久久久久久电影| 欧美成人精品xxx| 欧美日韩国产第一页| 在线观看久久av| 久久久999精品免费| 欧美大片在线看| 日本欧美在线视频| 成人性生交大片免费看小说 | 亚洲成人男人天堂| 日本视频一二三区中文字幕| 青青草视频免费在线观看| 高潮毛片在线观看| 日本精品另类| 亚洲人metart人体| 美腿丝袜亚洲色图| 日本一区二区成人| 欧美一级午夜免费电影| 中文字幕亚洲无线码a| 庆余年2免费日韩剧观看大牛| 久久久久久九九九九| av无码久久久久久不卡网站| 婷婷六月激情| 亚洲日本在线观看视频| 亚洲精品午夜av福利久久蜜桃| 国产乱国产乱300精品| 亚洲国产精品精华液网站| 精品久久久久久久人人人人传媒| 久久91精品国产91久久久| 国产精品对白一区二区三区 | 欧美无人高清视频在线观看| 国产69精品久久久| 中文字幕在线亚洲三区| 国内福利写真片视频在线| 欧美大片免费| 日韩天堂av| 一区二区三区日韩欧美| 中文在线资源观看视频网站免费不卡 | 亚洲先锋影音| 久久伊人蜜桃av一区二区| 欧美日本在线观看| 欧美中文在线免费| 国产3p露脸普通话对白| 黄色在线免费观看大全| 国产欧美日韩免费观看| 久久久久99精品国产片| 亚洲精品一区二三区不卡| 国产美女精品久久久| 在线视频你懂| 欧美国产美女| 亚洲一区二区三区免费视频| 久久伊人一区二区| 麻豆成人在线播放| 免费女人黄页| 精品三级av| 久久久电影一区二区三区| 日韩中文av在线| 国产又粗又大又爽的视频| 台湾佬中文娱乐久久久| 国内精品国产成人| 久久激情五月丁香伊人| 午夜肉伦伦影院| 成人资源在线播放| 《视频一区视频二区| 日韩av男人的天堂| 在线看国产视频| 99精品热6080yy久久| 精品国产污网站| 日本老太婆做爰视频| 日韩在线成人| 精品毛片三在线观看| 日韩在线观看电影完整版高清免费 | 日韩高清不卡在线|