CSCE 313 Lecture 12
« previous | Tuesday, February 28, 2012 | next »
UNIX I/O
- Files and File representation
- Basic operations: reading / writing
- Caching: open / close
- Multiplexing: select / poll
- File descriptors.
Files
A file is a collection of data elements, grouped together for the purpose of access control, retrieval, and modification.
Usually mapped onto physical storage devices (nonvolatile)
- read
- ssize_t read(int fildes, void &buf, size_t n_byte);
- write
- ssize_t write(int filedes, const void &buf, size_t n_byte);
Determining beginning and end of file:
- Character counter (number of bytes contained in this file.
- Character stuffing (use characters to signal beginning and end of file in data stream)
- Bit stuffig (similar to characters, only use bit pattern
- Physical ... violation ??
Bookkeeping
open file system call caches file info in kernel memory:
- Location of file on disk
- File pointer for read/write
- blocking information
- etc.
List maintained by entire system and by each process.
Opening/Closing Files
- int open(char *path, int flags, int mode);
- int close(int filedes);
Multiplexing
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval timeout);
Monitor multiple file descriptors from a single process.
Example
int main(void)
{
// initialize
FD_ZERO(&readset);
maxfd = 0;
for(int i=0; i<numfds; i++) {
// we're skipping error checking
FD_SET(fd[i], &readset);
maxfd = MAX(fd[i], maxfd);
}
// reading from multiple fd's
while (!done) {
numready = select(maxfd, &readset, NULL, NULL, NULL);
if ((numready == -1) && (errno == EINTR))
// interrupted by signal, continue monitoring
continue;
else if (numready == -1)
// a real error happened; abort monitoring
break;
for (int i=0; i<numfds; i++) {
if (FD_ISSET(fd[i], &readset)) {
// this descriptor is ready
bytesread = read(fd[i], buf, BUFSIZE);
done = TRUE;
}
}
}
return 0;
}
File Representation to User
ISO C file pointers point to a structure that contains file descriptor, buffer, etc.
FILE *myfp;
myfp = fopen("myfile.txt", "w");
File Descriptors and fork()
Child inherits the content of parent memory, including all open files and file descriptors.
Duplicating File Descriptors
int dup2(int fildes, int fildes2);
It closes fildes2 if open, and copies the pointer from fildes into fildes2.
Example:
int fd = open("file.txt", <flags>, <mode>);
dup2(fd, STDOUT_FILENO);
close(fd);
write(STDOUT_FILENO, "OK", 2);
After open() | After dup2() | After close(fd) |
---|---|---|
[0] standard input | [0] standard input | [0] standard input |
[1] standard output | [1] write to file.txt | [1] write to file.txt |
[2] standard error | [2] standard error | [2] standard error |
[3] write to file.txt | [3] write to file.txt |
Therefore, the output "OK" is written to file.txt.
File Control
int fcntl(int fildes, int cmd, /* arg */ ...);
Commands:
- F_DUPFD duplicate file descriptor
- F_GETFD get file descriptor flags
- F_SETFD set file descriptor flags
- F_GETFL get status flags and access modes
- F_SETFL set status flags and access modes
- F_GETOWN get owning process/thread ID
- F_SETOWN set owning process/thread ID
- F_GETLK get lock status on file descriptor
- F_SETLK set lock on a file descriptor
int setnonblock(int fd) {
int fdflags;
if ((fdflags = fcntl(fd, F_GETFL, 0)) == -1) return -1;
fdflags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, fdflags) == -1) return -1;
return 0;
}