Unix to Windows Porting Dictionary for HPC

Links

Function List

write


Unix

header file: unistd.h, uio.h

ssize_t write (int d, const void *buf, size_t nbytes);
ssize_t pwrite (int d, const void *buf, size_t nbytes, off_t offset);
ssize_t writev (int d, const struct iovec *iov, int iovcnt);

Windows

header file: io.h, or WinBase.h

int _write(int fd, const void *buffer, unsigned int count);
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
    LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);

Purpose

Write data to a device.

Discussion

The API's for writing to a device such as disks, terminals and sockets is widely used. Unix was originally designed to have strong consistency for how data is sent to different devices. To the orginal write() API two additional writing API's have been added over the years to provide more flexability about how the data is written or given to the API. The pwrite() API combines the lseek() and write() API's into one call (position file pointer and then write). The writev() API allows for the gathering of data from several different memory locations during a single write to the device. A special structure is iused to specify from where the data to is be gathered. Both blocking and non-blocking I/O can be done with these API's depending on how the original open was specified.

For portability Windows has the _write() API which must be used in conjunction with the _open() API. This is a helper function provided for portability. The other two Unix API's, pwrite() and writev(), require that you write your own or obtain them from elsewhere. The helper functions have a resource overhead versus the core Windows API. The easiest way of dealing with dealing with the lack of an ssize_t type in Windows is to either cast it as an int, or simply define it as an int directly (with "#define ssize_t int" or similar).

To port your code directly to the Windows API's you will use the WriteFile() API. The WriteFile() API can be used with many different devices including disks, tapes, pipes, mailslots and sockets. While WriteFile() has more arguments than the Unix API's its arguments are very similar. Whereas the Unix API's return the number of bytes written, the Windows API returns success or failure with the number of bytes written returned in an argument. The additional argument 'lpOverlapped' is used for asynchronous or non-blocking I/O when the file was opened for asynchronous I/O; for synchronous I/O this argument is NULL. Using the WriteFile() API directly will be faster and have less resource use than the _write() API.

Example of Use in Windows

int pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
{
        long ret = _lseek(fd, offset);

        if (ret == -1) {
                return(-1);
        }
        return(_write(fd, buf, nbytes));
}

HANDLE fh;
char buf[100];
DWORD written;
BOOL rez;

/* File previously opened for synchronous I/O */
rez = WriteFile(fh, buf, 90, &written, NULL);
if (rez) {
        /* Success for 'written' bytes */
}
else {
        /* Did not succeed */
}

blog comments powered by Disqus