我具有以下代码,用于读写使用FUSE实现的文件系统。该文件已映射到内存区域,我需要从文件系统中的内存读取到缓冲区。但是,即使read函数到达了return语句,在返回给调用者之前也会发生段错误。写入功能非常相似,并且可以正常工作。
我的读写功能如下所示:
// Write
int as3fs_write( filesystem *fs, char *path, void *buffer, size_t length ) {
// TODO check if file is open?
printf( "write - length to write: %ld\n", length );
// Find entry
entry *e = locate_entry( fs, path );
if ( e == NULL ) {
return -1; // NOT FOUND
}
node *n = (node*) getPointer( fs, e->data );
int wp = 0; // Write pointer
data_record *record;
data_record *new_record;
offset new_record_offset;
record = (data_record*) getPointer( fs, n->data_last );
// In case there are no records, make one
if ( record == NULL ) {
printf( "write - Creating new first record for this file\n" );
n->data_first = find_hole( fs, sizeof( data_record ) );
n->data_last = n->data_first;
data_record *new_record = getPointer( fs, n->data_first );
new_record->next = OFFSET_NULL;
new_record->length = 0;
record = new_record;
}
// Main loop, write data
while( wp < length ) {
// Write to record
size_t space_in_record = RECORD_SIZE - record->length;
size_t want_to_write = length - wp;
printf( "write - New record - wants to write %ld bytes, space in record for %ld bytes.\n", want_to_write, space_in_record );
// Check if the data fits in this record
if ( want_to_write <= space_in_record ) {
// Space for all data, write and exit
printf( "write - All remaining writeable data fit in this record.\n" );
memcpy( record->data + record->length, buffer + wp, want_to_write );
record->length += want_to_write;
// We are done, break out of while loop
wp += want_to_write;
break;
} else {
// Not space for all data, write available data and create new data record
printf( "write - Writing partially.\n" );
// First, write the data that we can write
memcpy( record->data + record->length, buffer + wp, space_in_record );
record->length += space_in_record;
// Create new record and restart loop and write the rest of the data
new_record_offset = find_hole( fs, sizeof( data_record ) );
new_record = (data_record*) getPointer( fs, new_record_offset );
new_record->length = 0;
new_record->next = OFFSET_NULL;
// Link in linked list
record->next = new_record_offset;
n->data_last = new_record_offset;
wp += space_in_record;
}
}
// Done writing data
e->size += length;
return wp;
}
// Read, return number of bytes read
int as3fs_read( filesystem *fs, char *path, void *buffer, size_t length ) {
printf( "read - started to read\n" );
// Find entry
entry *e = locate_entry( fs, path );
if ( e == NULL ) {
return -1; // NOT FOUND
}
printf( "Entry %s located\n", e->name );
node *n = (node*) getPointer( fs, e->data );
printf( "Node located\n" );
data_record *record = (data_record*) getPointer( fs, n->data_first );
printf( "Record found\n" );
int rp = 0; // Read pointer in buffer, represents number of bytes read
int want_to_read, data_available;
while( rp < length ) {
want_to_read = length - rp;
data_available = record->length;
// Check relation of bytes left to read and available bytes in record
if ( want_to_read <= data_available ) {
// We can read all the rest of the data from record
printf( "read - Able to read all data from this record. %d bytes. Current rp = %d. Buffer address: %x.\nWriting to address %x\n", want_to_read, rp, buffer, buffer + rp );
memcpy( buffer + rp, record->data, want_to_read );
rp += want_to_read;
printf( "buffer: %s\n", (char*) buffer );
break;
} else {
// Want to read more than what is in the record. Read this record and continue to next.
printf( "Reading partially\n" );
// Copy current record
memcpy( buffer+rp, record->data, data_available );
rp += data_available;
// Debug print memcpy data
printf( "buffer: %s\n", (char*) buffer );
if ( record->next == OFFSET_NULL ) {
// There is no more data after this, done reading
break;
}
// Reference the next record
record = (data_record*) getPointer( fs, record->next );
}
}
printf( "read - Success, rp = %d\n", rp );
return rp;
}
我制作了一个快速测试程序来测试功能:
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/mman.h>
#include "as3fs.h"
int main( int argc, const char* argv[] ) {
// Initialise filesystem
filesystem *fs = as3fs_init( "test_disk.img" );
// Traverse and print
traverse( fs, fs->root, print_entry );
hole_print( fs );
printf( "\n\nR/W TEST\n\n" );
char *writebuffer = malloc( 8000 * sizeof( char ));
char *readbuffer = malloc( 8000 * sizeof( char ) );
int res_write;
int res_read;
printf( "Allocated write buffer at %x, read buffer at %x\n", writebuffer, readbuffer );
strcpy( writebuffer, "din mor." );
res_write = as3fs_write( fs, "/testdir/fileintestdir", writebuffer, strlen( "abcdefgh") + 1 );
printf( "Write return code %d\n", res_write );
res_read = as3fs_read( fs, "/testdir/fileintestdir", readbuffer, strlen( "abcdefgh") + 1 );
printf( "returned from read\n" );
printf( "Read return code: %d\n", res_read );
//printf( "%s\n", readbuffer );
return 0;
}
我已经复制粘贴了测试程序输出的相关部分。其中一些行是从其他功能打印的:
R/W TEST
Allocated write buffer at b4471870, read buffer at b44737c0
write - length to write: 9
current_dir at start:
locate - Locate started, looking for directory /testdir
locate - first token is: testdir
locate - new string is testdir
locate - scanning entry testdir
locate - entering subdirectory testdir
locate - Finished successfully
write - Creating new first record for this file
Finding holes
Found hole at 4304, size = 77616
write - New record - wants to write 9 bytes, space in record for 4080 bytes.
write - All remaining writeable data fit in this record.
Write return code 9
read - started to read
current_dir at start:
locate - Locate started, looking for directory /testdir
locate - first token is: testdir
locate - new string is testdir
locate - scanning entry testdir
locate - entering subdirectory testdir
locate - Finished successfully
Entry fileintestdir located
Node located
Record found
read - Able to read all data from this record. 9 bytes. Current rp = 0. Buffer address: b44737c0.
Writing to address b44737c0
buffer: abcdefg
read - Success, rp = 9
[1] 23122 segmentation fault sudo ./as3fs_test_rw
我无法弄清楚怎么可能到达read函数的末尾,正如在测试程序中的下一条语句之前进行段错误时,通过“ read-success,rp = 9”行所确认的那样。