1 问题描述

在移植中间件过程中,在SylixOS调用write函数写入0字节的数据到文件中时,会导致对应的中间件测试用例失败,失败的原因是文件系统中的write函数在Linux系统和SylixOS有区别,两种实现的差别如下。

2 write函数的实现机制2.1 SylixOS实现机制

在SylixOS下通过write 函数写数据到普通文件中时,第一步会判断写入的数据是否为0,如果是0直接返回失败,具体实现如程序清单 2.1所示。

程序清单 2.1 SylixOS文件系统写函数

static ssize_t __ramFsPWrite (PLW_FD_ENTRY pfdentry,

PCHAR pcBuffer,

size_t stNBytes,

off_t oftPos)

{

PLW_FD_NODE pfdnode = (PLW_FD_NODE)pfdentry->FDENTRY_pfdnode;

PRAM_NODE pramn = (PRAM_NODE)pfdnode->FDNODE_pvFile;

ssize_t sstWriteNum = PX_ERROR;

if (!pcBuffer || !stNBytes || (oftPos < 0)) {

_ErrorHandle(EINVAL);

return (PX_ERROR);

}

if (pramn == LW_NULL) {

_ErrorHandle(EISDIR);

return (PX_ERROR);

}

if (__RAMFS_FILE_LOCK(pramn) != ERROR_NONE) {

_ErrorHandle(ENXIO);

return (PX_ERROR);

}

if (S_ISDIR(pramn->RAMN_mode)) {

__RAMFS_FILE_UNLOCK(pramn);

_ErrorHandle(EISDIR);

return (PX_ERROR);

}

sstWriteNum = __ram_write(pramn, pcBuffer, stNBytes, (size_t)oftPos);

if (sstWriteNum > 0) {

pfdnode->FDNODE_oftSize = (off_t)pramn->RAMN_stSize;

}

__RAMFS_FILE_UNLOCK(pramn);

return (sstWriteNum);

}

2.2 Linux实现机制

在Linux下通过write 函数写数据到普通文件中时,第一步会判断写入的数据是否为0,如果是0直接返回0,具体实现如程序清单 2.2所示。

程序清单 2.2 Linux 文件系统写函数

ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,

unsigned long nr_segs, loff_t *ppos)

{

struct file *file = iocb->ki_filp;

struct address_space * mapping = file->f_mapping;

size_t ocount; /* original count */

size_t count; /* after file limit checks */

struct inode *inode = mapping->host;

loff_t pos;

ssize_t written;

ssize_t err;

ocount = 0;

err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);

if (err)

return err;

count = ocount;

pos = *ppos;

/* We can write back this queue in page reclaim */

current->backing_dev_info = mapping->backing_dev_info;

written = 0;

err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));

if (err)

goto out;

if (count == 0)

goto out;

err = file_remove_suid(file);

if (err)

goto out;

err = file_update_time(file);

if (err)

goto out;

/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */

if (unlikely(file->f_flags & O_DIRECT)) {

loff_t endbyte;

ssize_t written_buffered;

written = generic_file_direct_write(iocb, iov, &nr_segs, pos,

ppos, count, ocount);

if (written < 0 || written == count)

goto out;

/*

* direct-io write to a hole: fall through to buffered I/O

* for completing the rest of the request.

*/

pos += written;

count -= written;

written_buffered = generic_file_buffered_write(iocb, iov,

nr_segs, pos, ppos, count,

written);

/*

* If generic_file_buffered_write() retuned a synchronous error

* then we want to return the number of bytes which were

* direct-written, or the error code if that was zero. Note

* that this differs from normal direct-io semantics, which

* will return -EFOO even if some bytes were written.

*/

if (written_buffered < 0) {

err = written_buffered;

goto out;

}

/*

* We need to ensure that the page cache pages are written to

* disk and invalidated to preserve the expected O_DIRECT

* semantics.

*/

endbyte = pos + written_buffered - written - 1;

err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);

if (err == 0) {

written = written_buffered;

invalidate_mapping_pages(mapping,

pos >> PAGE_CACHE_SHIFT,

endbyte >> PAGE_CACHE_SHIFT);

} else {

/*

* We don't know how much we wrote, so just return

* the number of bytes which were direct-written

*/

}

} else {

written = generic_file_buffered_write(iocb, iov, nr_segs,

pos, ppos, count, written);

}

out:

current->backing_dev_info = NULL;

return written ? written : err;

}