Tirgul 1 C File System Calls: int open(char* filename, int flag ) – creates a file descriptor number for the given file and returns its number the file descriptor is given the permissions as specified by the flag Returns the fd’s number or -1 in case of error Example: int fd = open("dugma1.txt", O_RDONLY ); - opens the file dugma1.txt for read only int fd = open( "OPEN.OUT", O_WRONLY | O_CREAT ); - creates and opens the file for writing only Note – it is also possible to use open( char* filename, int flag, int permissions) and then if this call creates a new file then permissions represents this file permissions int close( int fd ) – closes the file descriptor with the given number returns -1 in case of error or if the file was successfully closed int read(int fd , void* buffer , unsigned int count) returns -1 if error, if reached EOF on start, a number n between and count if n bytes were actually read Example: int readAmount = read(fd,buf,30); int write(int fd, void* buffer, unsigned int count) returns -1 if error, or the number of bytes actually written (in cases like disk full this number can be different from count ) long lseek(int fd, long offset , int startingPositionDeclaration) moves the file pointer of the given file descriptor to the specified location startingPositionDeclaration may be one of : SEEK_SET (beginning of file), SEEK_CUR (current position of file pointer), SEEK_END (end of file) lseek will move the file pointer to the location declared, then move it another offset bytes from that location Returns -1 if error, or the offset in bytes (from start of file) of the new file pointer location Note – read and write also move the file pointer with every call If n bytes were actually read (or written), then the file pointer is advanced by n bytes int dup(int fd) creates another file handle for the open file with the given file descriptor Returns -1 in case of error, or the file descriptor number for the new handle created The file handle number allocated is the first (lowest) free file handle number Example: int mosheFD = open(“moshe.txt”…); close(1); // closes file handle 1, which is stdout int fd =dup(mosheFD); // will create another file handle for “moshe.txt”, it just so // happends file handle number is free, so it will be allocated close(mosheFD); // don’t need this fd anymore printf(“this did not go to stdout”); errno you can include errno.h and whenever an error from the above calls occurs, find out exactly what was the error by comparing the variable int errno declared in this header file to constants representing different error types Look in the detailed description of the system calls to find out what constants mean what errors example: int x = write(fd, buf, 10); if (x==-1) { if (errno==EBADF) perror(“file handle is invalid or not open for writing”); if (errno==ENOSPC) perror(“not enough free space”); } more details can be see by: a using man in linux or msdn in Microsoft Visual C++ help b Using unix command ‘whereis ’ to locate files such as stdio.h that define constants (usually found in /user/include and /user/include/sys) c see additional word documents found on our website Combined example (tirgul1_1.c): #include #include #include #define GODEL 10 main(int argc , char argv) { int fdin; /* int fdout; /* char *buf[GODEL+1]; /* int camar; /* int camaw; /* input file descriptor */ out file descriptor */ input (output) buffer */ how many chars were actually red */ how many chars were actually written */ memset(buf,0,GODEL+1); /* just cleaning the buffer for no good reason */ fdin = open("dugma1.txt",O_RDONLY); if (fdin < 0) { /* means file open did not take place */ perror("after open "); /* text explaining why */ exit(-1); } fdout = open("dugma2.txt", O_CREAT | O_RDWR, 0466); /* create the file with read only premissions */ if (fdout < 0) { /* means file open did not take place */ perror("after create "); /* text explaining why */ exit(-1); } { camar = read(fdin,buf,GODEL); camaw = write(fdout,buf,GODEL); // why writting GODEL can be wrong if (camaw < GODEL) { if (errno == EDQUOT) printf(" I need more space \n"); else if (errno == ENOSPC) printf("sys admin: clean the disk \n"); } } while ( (camar == GODEL) && (camaw == GODEL)); lseek(fdout,0,SEEK_SET); write(fdout,"The Start", 10); close(fdin); /* free allocated structures */ close(fdout); /* free allocated structures */ } C Processes System Calls: int fork() The fork system call in Unix creates a new process The new process inherits various properties from its parent (Environmental variables, File descriptors, etc see the manual page for details) After a successful fork call, two copies of the original code will be running In the original process (the parent) the return value of fork will be the process ID of the child In the new child process the return value of fork will be can return -1 if error (for example, reached max amount of processes – no more space for any more process control boxes) int getpid() return this process’s ID int execvp( char* commandName, char** argv ) loads and executes a new process, passing an array of pointers as command-line argument commandName – path of file to execute argv – array of pointers to parameters return -1 if error If there is no error, there will be no return value ! int wait(int *status) wait suspends the calling process until one of the immediate children terminate, or until a child that is being traced stops because it has hit an event of interest.If all child processes stopped or terminated prior to the call on wait, return is immediate If the call is successful, the process ID of a child is returned status will be set with information about the child process which stopped You can use macros (detailed in man wait) to extract this information from status int waitpid(int pid , int *status, int options) is similar to wait only it waits for the specific child who’s id is pid See more info in the man pages More details at: man pages , http://www.mcsr.olemiss.edu/cgi-bin/man-cgi?wait+2 , our website Examples: Simple example: pid = fork(); if (pid == 0) { /* son */ ret_code = execvp(argv[1],argv); if (ret_code == -1) { perror("exec failed "); exit(-1); } else /* this cannot be reached WHY????*/ ; } else { /* father */ printf("Father: after fork, son proc id is %d \n",pid); waited = wait(&stat); /* stat can tell what happened */ printf("Father: Son proc completed, id is %d \n", waited); } Shell example: while (true) type_prompt(); // display prompt on the screen read_command(command, params); // read input pid = fork(); if (pid < 0) { printf("unable to fork"); //error condition continue; } if (pid > 0) { //parent code wait(&status); // what happends if we don’t wait ? } else { //child code execvp(command, params); } } fork + redirection example: fd = open (“moshe.txt” , (O_WRONLY | O_CREAT | O_TRUNC) , 0666); pid = fork(); if (pid == 0) { /* son */ printf("Son : %d ;file descriptor: %d \n",getpid(),fd); close(1); /* close stdout*/ dup(fd); /* dup will copy fd into stdout */ close(fd); /* no need for fd anymore*/ ret_code = execvp("hadpes",argv); /*always same exe*/ if (ret_code == -1) { perror("exec failed "); exit(-1); } } else { /* father */ printf("Father: after fork, sons proc id is %d \n", pid); waited = wait(&stat); sprintf (msg, "father caught %d\n" , waited); write(1, msg, strlen(msg)); /* writting to “stdout” */ } the hadpes.c file: #include main(){ perror(“hadpes start\n”); printf(“hello world\n”); perror(“hadpes end\n”); } output: Son : 18601 file descriptor: Father: after fork, son proc id is 18601 hadpes start hadpes end father caught 18601 and the file “moshe.txt” will contain the string “hello world” References: All the above used system-calls are described in details at the ‘msdn’(Microsoft Visual C++ help) and in the UNIX manual open.doc, read.doc, close.doc, write.doc, lseek.doc,, dup.doc, execvp.doc, fork, getpid.doc, wait ... world
”); perror(“hadpes end
”); } output: Son : 18 6 01 file descriptor: Father: after fork, son proc id is 18 6 01 hadpes start hadpes end father caught 18 6 01 and the file “moshe.txt” will contain the... Combined example (tirgul1 _1. c): #include #include #include #define GODEL 10 main(int argc , char argv) { int fdin; /* int fdout; /* char *buf[GODEL +1] ; /* int camar;... example: pid = fork(); if (pid == 0) { /* son */ ret_code = execvp(argv [1] ,argv); if (ret_code == -1) { perror("exec failed "); exit( -1) ; } else /* this cannot be reached WHY????*/ ; } else { /* father