2012-03-27 2 views
1

Привет, я пишу драйвер char, который читает и записывает на конкретное устройство. Поскольку я - noob, это очень простой и простой диск, который использует только самые простые протоколы, такие как открытие, чтение, запись и выпуск. Чтобы проверить мой драйвер, я использую следующую программу ... bellow - это источник для моей программы пользовательского пространства.В каком порядке выполняется код пространства пользователя?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <signal.h> 
#include <poll.h> 

int main(void){ 
int num; 
char *buff; 
FILE *fd = fopen("/dev/hi","a+"); 
num = fprintf(fd,"this is sentence 1 !!"); 
num = fprintf(fd,"this is sentence 2 !!"); 
num = fprintf(fd,"this is sentence 3 !!"); 
num = fprintf(fd,"this is sentence 4 !!"); 
num = fprintf(fd,"this is sentence 5 !!"); 
buff = malloc(sizeof(char) * num+1); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
free(buff); 
close(fd); 
return 0; 
} 

Теперь не важно, как работает мой драйвер, но в каком порядке я называю свои методы чтения и записи. В идеале было бы неплохо, если бы водитель записывался в том порядке, в котором я написал свой код и читал в том порядке, в котором я написал свой код. Однако я заметил, что если бы я написал свой код, как ...

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <arpa/inet.h> 
#include <signal.h> 
#include <poll.h> 

int main(void){ 
int num; 
char *buff; 
FILE *fd = fopen("/dev/hi","w"); 
num = fprintf(fd,"this is sentence 1 !!"); 
num = fprintf(fd,"this is sentence 2 !!"); 
num = fprintf(fd,"this is sentence 3 !!"); 
num = fprintf(fd,"this is sentence 4 !!"); 
num = fprintf(fd,"this is sentence 5 !!"); 
    close(fd); 
    fd = fopen("/dev/hi","r"); 
buff = malloc(sizeof(char) * num+1); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
fread(buff,sizeof(char),num+1,fd); 
printf("%s\n",buff); 
free(buff); 
close(fd); 
return 0; 
} 

Я заметил, что fprintf() пишет только, когда я закрываю дескриптор файла и худшее еще, выполняется после того, как я прочитал с устройства. Конечно, я хочу писать на свое устройство, а затем читать, но этого не происходит. Это создает у меня впечатление, что многие вещи в пользовательском пространстве выполняются одновременно, что меня озадачивает. Как узнать, какой порядок функций моего устройства вызывается при работе с пользовательским пространством. Извините, если это кажется расплывчатым, я расскажу о чем-нибудь, что является мирским.

Спасибо за любые ответы !!

+3

Я бы использовал системный вызов 'write', а не' fprintf' или 'fputs' из стандартной библиотеки. Или, по крайней мере, называть 'fflush' очень часто. –

+0

Спасибо за помощь! –

ответ

4

Ваши записи в 'fd' кэшируются и записываются только в драйвер устройства после его закрытия. Это нормально и сделано для уменьшения количества системных вызовов.

Если вам действительно нужна каждая запись для отправки на устройство, попробуйте добавить вызов fsync() после каждой записи. В качестве альтернативы, поскольку это драйвер char, скорее всего, это строка буферизации, попробуйте добавить '\ n' в конце каждой строки.

+2

fsync не сделает этого, так как он использует FILE * (и называет их fds ;-), но fflush должен это сделать. – flolo

+0

Я думаю, что добавление новых строк также предотвратит буферизацию. – ugoren

1

Просмотрите fflush или fsync, чтобы очистить буферизованный выход и зафиксировать записи перед выполнением ваших чтений.

+0

Обратите внимание, что fflush принимает аргумент FILE *, а не дескриптор файла. Вместо этого он хочет fsync. –

+1

@ KristofProvost: нет fflush, путаница исходит из того факта, что оригинальный плакат использует FILE * и называет его fd. – flolo

+0

О, да. Я действительно должен знать лучше, чем ожидать, что переменная fd будет содержать файловый дескриптор. –

2

Код в пользовательском пространстве выполнен в порядке (за исключением того, что вы работаете с параллелизмом или какой-либо другой концепцией, которая смешивает порядок).

Я подозреваю, что то, что вы интерпретируете как «мирки», происходит от буферизации fprintf.

Вы можете сбросить буферы, позвонив по номеру fflush(fd) после каждого fprintf. И вы можете отключить его, когда звоните заранее setbuf(fd, NULL).

0

Как говорили другие, речь идет о буферизации, а не о некоторых необычных исполнениях порядка исполнения. Используйте fflush, чтобы очистить поток и фактически записать данные, или использовать нижние уровни , и написать и т. Д. Звонки.

Но другое дело, что я думаю, что следует отметить:

Вы, кажется, есть некоторая путаница происходит относительно потоков и дескрипторов файлов. Вы вызываете свой FILE * «fd», а затем говорите, что это файловый дескриптор. Но файл FILE * - это поток, а не файловый дескриптор. Дескриптор файла - это вещь более низкого уровня, которая скрыта библиотекой stdio.

Linux предоставляет дескрипторы файлов, которые вы получите, позвонив открытый, а затем вы можете использовать записи писать в этот файл дескриптора и закрыть его с близко. STDIO библиотека добавляет еще один уровень, со своими собственными вызовами (Еореп, FWRITE, fprintf, fclose и т.д.), и его собственной буферизацией, поверх файловых дескрипторов.

Также обратите внимание, что вы должны использовать fclose, чтобы закрыть поток, а не близко.