INTERACTING WITH USER AND SYSTEM
1. Operating System
-Most interesting interactions that read inputs and write a file require access to hardware devices. It requires the permission from permissions system.
-The program asks the operating system to access hardware. It makes the request via a system call. It transfer control from the program into the operating system. The operating system checks that the program's request is within the bounds of its permissions before performing it.
-It's more common to use functions in the C library than system calls.
-printf is not part of the C library and includes significant code which does not require system calls. BUT it does contain a system call in some cases. It is not correct to cal printf a system call.
2. Errors in System Calls
-Errors include: read a file that does not exist or does not have permissions for.
-Whenever system calls fails, their wrapper in the C library set a global variable called 'errno'.
-To know why the call failed, we can compare it against the various constants defined in errno.h. Or we can refer to 'perror', which resides in C library and will print a edscriptive error message based on the current value of errno.
-We should not call anything that might cause 'errno' to change before we call 'perror'.
3. Command Line Arguments
-One type of input our programs can take is command line arguments. For example, in "gcc -o hello hello.c" we are passing the arguments: name(gcc) to GCC. However, we don't generally think its name to be one arguments.
4. Command Line Arguments
-In gcc -o myProgram mypRogram.c, -o option itselfe takes an argument: the next command line argument (In this command line, myProgram)after it.
-'getopt' function parses the command line arguments, accounting for such considerations as options that have arguments, as well as short and long name versions. (e.g. -o and --output are the same but difference is that one is long and one is short)
5. Environment Pointer
-'main' can take a third argument: char**envp, a pointer to an array of strings containing the value of environment variables.
-If you include this, th elements of the array are strings of the form variable=value (PATH=/bin:/usr/bin). We can also access environment variables using the function getenv, setenv, putenv, and unsetenv.
6. Process Creation
-When the command shell wants to run another program, it makes several system calls. First, it makes a call to create a new process. The new process then makes another system call (execve) to replace its running program with the requested program. The execve system call takes the file with binary to run. A second argument pass the new program as argv and a third argument specifying the values to pass for envp.
-execve -> destroy currently running program -> write argv and envp -> set execution arrow to start location -> startup ocde calls various functions that initialize C library
-When main returns, it returns to the function that called it. It is the startup code that calls it. Then this code performs any cleanup required by the C library and calls exit, passing in the return value of main as the argument of exit.
6. Files
-Opening a file causes a stream associated with the file. A stream is a sequence of data that can be read and written.
-We can use fopen function to open a file. The prototype of fopen is:
FILE * fopen (const char * filename, const char *mode);
-It takes two arguments, the first is the pathname of the file to open. It can either be an absolute path, or a path relative to the current working directory.
-The second argument is the mode of the file: Whether the file should be opened for reading or writing, whether to create a file if it does not exist, whether existing content is cleared out, etc.
-Real FILE structs do not contain the name of the file, but rather a file descriptor -- a numeric identifier returned to the program by the operating system.
-It's possible for fopen to fail when the file requested does not exist, or does not have the permissions required to access it. Whenever it fails, it returns NULL, and sets errno appropriately. We should check the return value of fopen before we attemp to use the stream.
Modes for fopen:
mode read and/or write does not exist? truncate? position
r read only fails no begining
r+ read/write fails no begining
w write only created yes begining
w+ read/write created yes begining
a writing created no end
a+ read/write created no end
7. Reading Files
-We can use one of three functions to read files: fgetc, fgets, fread. fgetc is useful when you want to read one character at a time.
-fgetc returns an int so that it can return all possible chars plus a distinct value to indicate the end of file has been reached. The value for end-of-file is defined as the constant EOF in stdio.h.
FILE * f = fopen(inputfilename,"r");
if(f==NULL){}
while(fgetc(f) != EOF) {
char c = fgetc(f); //evaluate to fgetc(f)
printf("%c", c);
}
or
FILE * f = fopen(inputfilename,"r");
if(f==NULL){}
while(c=fgetc(f) != EOF) {
printf("%c", c);
}
-fgets is useful when you want to read one line. It has the following prototype:
char * fgets(char * str, int size, FILE * stream);
-It will write data into str[0], str[1], str[2] and so on. The second argument specifies the size of the array str. The final argument specifies what stream to read the data.
-It returns str if it succeeds. The data in str is null-terminated. It returns NULL if it fails. We can use feof and ferror to specify if it meets EOF or some other errors.
-We should never use 'gets'. This function will continue to read data until it reaches a newline. This function therefore poses a significant security vulnerability.
-When we want to read data from image, video, sound or other file, the most appropriate function is fread. The prototype of fread is as following:
size_t fread (void * ptr, size_t size, size_t nitems, FILE * stream);
-The first argument is a pointer to the data to write. The next one is the size of each item. The third argument specifies how many such items should be read from the stream and the final argument specifies which stream to read. fread returns how many items were successfully read.
-We can use feof and ferror to obtain more information if it returns fewer items than we requested.
- We can use fscamf tp read formatted input. It will stop reading input as soon as it encounters something that does not match the requested format.
8. Writing Files
-fprintf function is useful when we want to print formatted text. It performs same as printf function, except that it takes and additional argument: FILE* to specifying where to write the output.
-We can also use fputc to write a single character at a time or use fputs to write a string without format conversions. It means, if we do fputs("%d"), it will print %d directly, rather than attempting to convert and integer and print it.
-We can use fwrite to print non-textual data.
9. Closing Files
-After finishing with a file, we should close it with fclose function. Prototype is following:
int fclose(FILE * stream);
-Closing the stream sends any buffered write data to OS and then asks the OS to close the associated file descriptor. After closing it, we may no longer access it. (i.e. using fgetc, fprintf, etc.)
-fclose returns an int. It indicates the success or failure. It can fail when the disk is full, or the file resides on a remote file system and network connectivity has been lost. Failure of fclose is a serious situation. It means the data your program tries to write may be lost. So, we should always check the return value of fclose to see if it fails or not.
-When fclose fails, we should not perform any operation on the stream, including another call to fclose. What we should do depends.
summary& understanding after reading <<All of Programming>> chapter 11
Comments
Post a Comment