Sunday, November 9, 2014

Unix Prog: readn, writen

1. readn, writen
read system call may return less than asked for, even though we have not encountered the end of file.
write system call may also return less than we specified. This may be caused by flow control constraints by downstream modules.

Above issues should never happen when reading writing a disk file, except when the file system runs out of space or we hit our quota limit and we can't write all that we requested

readn, writen simply call read or write as many times a required to read or write the entire N bytes of data.

2. System Definition:
Linux seems doesn't support these two functions
Unix system definition
 ssize_t readn(int filedes, void *buff, size_t nbytes);  
 ssize_t writen(int filedes, const void *buff, size_t nbytes);  

Given file descriptor, buffer, nbytes, these two function just try as many times as they can to read/write nbytes data.

3. Sample Implementation:
vio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<fcntl.h>  
   
 ssize_t readn(int fd, void *ptr, size_t n)  
 {  
  size_t nleft;  
  ssize_t nread;  
   
  nleft = n;  
  while(nleft > 0) {  
   if((nread = read(fd, ptr, nleft)) < 0) {  
    if(nleft == n)  
     return -1;  
    else  
     break;  
   } else if(nread == 0) {  
    break;  
   }  
   
   nleft -= nread;  
   ptr += nread;  
  }  
   
  return n-nleft;  
 }  
   
 ssize_t writen(int fd, const void* ptr, size_t n)  
 {  
  size_t nleft;  
  ssize_t nwritten;  
   
  nleft = n;  
  while(nleft > 0) {  
   if((nwritten = write(fd, ptr, nleft)) < 0) {  
    if(nleft == n)  
     return -1;  
    else  
     break;  
   } else if (nwritten == 0) {  
    break;  
   }  
   
   nleft -= nwritten;  
   ptr += nwritten;  
  }  
   
  return n-nleft;  
 }  
   
 int main(int argc, char* argv[])  
 {  
  int fd;  
  char buf1[10] = "Hello\n";  
  char buf2[10];  
  if((fd = open(argv[1], O_RDWR | O_CREAT)) < 0) {  
   printf("open error!\n");  
   exit(1);  
  }  
   
  writen(fd, buf1, 6);  
  lseek(fd, SEEK_SET, 0);  
  readn(fd, buf2, 6);  
   
  printf("buffer read out: %s\n", buf2);  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./vio.out test.txt  
 buffer read out: Hello  

No comments:

Post a Comment