Форум программистов, компьютерный форум, киберфорум
Debian, Kali Linux, Raspbian, Astra Linux
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
7 / 7 / 1
Регистрация: 14.11.2012
Сообщений: 73
1

Драйвер чтения и записи

22.12.2013, 12:16. Показов 1115. Ответов 0
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Мне нужно было реализовать драйвер, который поддерживает чтение и запись сообщений в него через пользовательский процесс, а также поддерживает функцию удаления сообщения. Первую функцию реализовать удалось ioctl_set_msg(file_desc, msg). Помогите, пожалуйста реализовать функцию удаления сообщения ( вызов происходит в ioctl.c).
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
* 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 <linux/ioctl.h>
/* 
* The major device number. We can't 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 we're creating an ioctl command 
* number for passing information from a user process
* to the kernel module. 
*
* The first arguments, MAJOR_NUM, is the major device 
* number we're 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 n'th 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
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
* ioctl.c - the process to use ioctl's to control the kernel module
*
* Until now we could have used cat for input and output. But now
* we need to do ioctl's, which require writing our own process.
*/
/* 
* device specifics, such as ioctl numbers and the
* major device file. 
*/
#include "chardev.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> /* open */
#include <unistd.h> /* exit */
#include <sys/ioctl.h> /* 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 don't tell
* the kernel how far it's 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;
do {
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);
if (c < 0) {
printf
("ioctl_get_nth_byte failed at the %d'th byte:\n",
i);
exit(-1);
}
putchar(c);
} while (c != 0);
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("Can't 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);
}
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
* chardev.c - Create an input/output character device
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/fs.h>
#include <asm/uaccess.h> /* for get_user and put_user */
#include "chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev"
#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 is called whenever a process attempts to open the device file 
*/
static int device_open(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_open(%p)\n", file);
#endif
/* 
* We don't want to talk to two processes at the same time 
*/
if (Device_Open)
return -EBUSY;
Device_Open++;
/*
* Initialize the message 
*/
Message_Ptr = Message;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
#endif
/* 
* We're now ready for our next caller 
*/
Device_Open--;
module_put(THIS_MODULE);
return SUCCESS;
}
/* 
* This function is called whenever a process which has already opened the
* device file attempts to read from it.
*/
static ssize_t device_read(struct file *file, /* see include/linux/fs.h */
char __user * buffer, /* buffer to be
* filled with data */
size_t length, /* length of the buffer */
loff_t * offset)
{
/* 
* Number of bytes actually written to the buffer 
*/
int bytes_read = 0;
#ifdef DEBUG
printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
#endif
/* 
* If we're 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 wouldn't
* 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(KERN_INFO "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. 
*/
static ssize_t
device_write(struct file *file,
const char __user * buffer, size_t length, loff_t * offset)
{
int i;
#ifdef DEBUG
printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
#endif
for (i = 0; i < length && i < BUF_LEN; i++)
get_user(Message[i], buffer + i);
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,*/ /* see include/linux/fs.h */
struct file *file, /* ditto */
unsigned int ioctl_num, /* number and param for ioctl
*/
unsigned long ioctl_param)
{
int i;
char *temp;
char ch;
/* 
* 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 device's message. Get the parameter given to 
* ioctl by the process. 
*/
temp = (char *)ioctl_param;
/* 
* Find the length of the message 
*/
get_user(ch, temp);
for (i = 0; ch && i < BUF_LEN; i++, temp++)
get_user(ch, temp);
device_write(file, (char *)ioctl_param, i, 0);
break;
case IOCTL_GET_MSG:
/* 
* Give the current message to the calling process - 
* the parameter we got is a pointer, fill it. 
*/
i = device_read(file, (char *)ioctl_param, 99, 0);
/* 
* Put a zero at the end of the buffer, so it will be 
* properly terminated 
*/
put_user('\0', (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;
}
/* 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 can't be local to
* init_module. NULL is for unimplemented functions. 
*/
struct file_operations Fops = {
.read = device_read,
.write = device_write,
.unlocked_ioctl = device_ioctl,
.open = device_open,
.release = 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 = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);
/* 
* Negative values signify an error 
*/
if (ret_val < 0) {
printk(KERN_ALERT "%s failed with %d\n",
"Sorry, registering the character device ", ret_val);
return ret_val;
}
printk(KERN_INFO "%s The major device number is %d.\n",
"Registeration is a success", MAJOR_NUM);
printk(KERN_INFO "If you want to talk to the device driver,\n");
printk(KERN_INFO "you'll have to create a device file. \n");
printk(KERN_INFO "We suggest you use:\n");
printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
printk(KERN_INFO "The device file name is important, because\n");
printk(KERN_INFO "the ioctl program assumes that's the\n");
printk(KERN_INFO "file you'll use.\n");
return 0;
}
/* 
* Cleanup - unregister the appropriate file from /proc 
*/
void cleanup_module()
{
//int ret;
/* 
* Unregister the device 
*/
/*ret = */unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
/* 
* If there's an error, report it 
*/
//if (ret < 0)
//printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
}
Добавлено через 11 часов 39 минут
То есть устройство с помощью драйвера записывает данные в свой узел. Как можно очистить этот узел?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.12.2013, 12:16
Ответы с готовыми решениями:

Драйвер для чтения из файла и записи в файл последних 20 слов
Нужно скопировать последние 20 слов с одного текстового файла в другой За основание берем две...

Драйвер для чтения CD-ROM
Есть код программы, которая должна считывать данные с CD-ROM'а. Скажите, он правильный или нет?...

Драйвер чтения данных из СОМ-порта(Ассемблер)
Доброго времени суток,может завалялся у кого драйвер DOS на ассемблере под COM-порт(без разницы на...

Mini-filter драйвер - Перехват открытия, закрытия, чтения файлов
здраствуйте, пожалуйста, помогите в создании mini-filter драйвер, а точнее драйвер файловой...

0
22.12.2013, 12:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.12.2013, 12:16
Помогаю со студенческими работами здесь

Написать функции для чтения/записи отдельных бит для любой записи из данного набора
Начиная с адреса А в памяти МК находятся N записей длиной k бит каждая. Записи выровнены по границе...

Рабочий драйвер FAT32 на fasm с функцией чтения файла по заданному пути
Мне нужен рабочий драйвер FAT32 на fasm. Функции драйвера: чтение файла по заданному пути....

Чтения записи в реестре
Помогите добрые люди пожалуйста:cry: Ни в какую не могу прочесть запись в реестре Делаю так Dim...

Потоки чтения и записи.
Здравствуйте, помогите пожалуйста разобраться с потоками чтения и записи информации. Проблема...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru