Upload
takeaxe
View
217
Download
0
Embed Size (px)
Citation preview
7/31/2019 System Calls Resources
1/15
System Calls
System calls are special set of functions available in several programming languages. They are used by
programs to communicate directly with an operating system. The operating system communicates back
to the user's program through the return value of the function.
Generally, system calls are slower than normal function calls. The reason is because when you call a
system call, control is relinquished to the operating system to perform the system call. In addition,
depending on the nature of the system call, your program may be blocked by the OS until the system
call has finished, thus making the execution time of your program even longer.
One rule of thumb should always be followed when calling a system call: Always check the return value.
The return value is the only method that the operating system has to communicate information to your
program. Thus, you should always check the return value in the event that the system call failed.
system() :
The system() call will execute an OS shell command as described by a character
command string. This function is implemented using fork(), exec() and waitpid(). The
command string is executed by calling /bin/sh -c command-string. During execution of
the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored. The
call "blocks" and waits for the task to be performed before continuing.
1 #include
2 #include
3 main()
4 {
5 system("ls -l");
6 printf("Command done!");
7/31/2019 System Calls Resources
2/15
7 }
The statement "Command done!" will not print untill the "ls -l" command has completed.
fork():
The fork() system call will spawn a new child process which is an identical process to
the parent except that has a new system process ID. The process is copied in memory
from the parent and a new process structure is assigned by the kernel. The return value
of the function is which discriminates the two threads of execution. A zero is returned by
the fork function in the child's process.
The environment, resource limits, umask, controlling terminal, current working directory,
root directory, signal masks and other process resources are also duplicated from the
parent in the forked child process.
[Potential Pitfall]: Some memory duplicated by a forked process such as file pointers,
will cause intermixed output from both processes. Use the wait() function so that the
processes do not access the file at the same time or open unique file descriptors. Some
like stdout or stderr will be shared unless synchronized using wait() or some other
mechanism. The file close on exit is another gotcha. A terminating process will close
files before exiting. File locks set by the parent process are not inherited by the child
process.
[Potential Pitfall]: Race conditions can be created due to the unpredictability of when the
kernel scheduler runs portions or time slices of the process. One can use wait(). the
use of sleep() does not guarentee reliability of execution on a heavily loaded system as
the scheduler behavior is not predictable by the application.
The fork() System Call
7/31/2019 System Calls Resources
3/15
System call fork() is used to create processes. It takes no arguments and returns a process ID. The
purpose offork() is to create a new process, which becomes the childprocess of the caller. After a
new child process is created, both processes will execute the next instruction following thefork()
system call. Therefore, we have to distinguish the parent from the child. This can be done by
testing the returned value offork():
Iffork() returns a negative value, the creation of a child process wasunsuccessful.
fork() returns a zero to the newly created child process.
fork() returns a positive value, theprocess ID of the child process, to the
parent. The returned process ID is of type pid_t defined in sys/types.h.Normally, the process ID is an integer. Moreover, a process can use functiongetpid() to retrieve the process ID assigned to this process.
Therefore, after the system call to fork(), a simple test can tell which process is the
child. Please note that Unix will make an exact copy of the parent's address
space and give it to the child. Therefore, the parent and child processeshave separate address spaces.
Let us take an example to make the above points clear. This example does not distinguish parent
and the child processes. Clickhereto download this file fork-01.c.
#include #include #include
#define MAX_COUNT 200
#define BUF_SIZE 100
void main(void){
pid_t pid;int i;char buf[BUF_SIZE];
fork();pid = getpid();for (i = 1; i
7/31/2019 System Calls Resources
4/15
If the call to fork() is executed successfully, Unix will
make two identical copies of address spaces, one for the parent and the otherfor the child.
Both processes will start their execution at the next statement following thefork() call. In this case, both processes will start their execution at theassignment statement as shown below:
Both processes start their execution right after the system call fork(). Since both processes haveidentical but separate address spaces, those variables initialized before the fork() call have the
same values in both address spaces. Since every process has its own address space, any
modifications will be independent of the others. In other words, if the parent changes the value of
its variable, the modification will only affect the variable in the parent process's address space.Other address spaces created by fork() calls will not be affected even though they have identical
variable names.
7/31/2019 System Calls Resources
5/15
What is the reason of using write rather than printf? It is because printf() is "buffered," meaning
printf()will group the output of a process together. While buffering the output for the parent
process, the child may also use printf to print out some information, which will also be buffered.As a result, since the output will not be send to screen immediately, you may not get the right order
of the expected result. Worse, the output from the two processes may be mixed in strange ways. To
overcome this problem, you may consider to use the "unbuffered" write.
If you run this program, you might see the following on the screen:
................This line is from pid 3456, value 13This line is from pid 3456, value 14
................This line is from pid 3456, value 20This line is from pid 4617, value 100This line is from pid 4617, value 101
................This line is from pid 3456, value 21
This line is from pid 3456, value 22................
Process ID 3456 may be the one assigned to the parent or the child. Due to the fact
that these processes are run concurrently, their output lines are intermixed in a
rather unpredictable way. Moreover, the order of these lines are determined by the
CPU scheduler. Hence, if you run this program again, you may get a totally different
result.
Consider one more simple example, which distinguishes the parent from the child. Clickhereto
download this file fork-02.c.
#include #include
#define MAX_COUNT 200
void ChildProcess(void); /* child process prototype */void ParentProcess(void); /* parent process prototype */
void main(void){
pid_t pid;
pid = fork();
if (pid == 0)ChildProcess();else
ParentProcess();}
void ChildProcess(void){
int i;
http://www.csl.mtu.edu/cs4411/www/NOTES/process/fork/fork-02.chttp://www.csl.mtu.edu/cs4411/www/NOTES/process/fork/fork-02.chttp://www.csl.mtu.edu/cs4411/www/NOTES/process/fork/fork-02.c7/31/2019 System Calls Resources
6/15
for (i = 1; i
7/31/2019 System Calls Resources
7/15
In the parent, since pid is non-zero, it calls function ParentProcess(). On the other hand, the childhas a zero pid and calls ChildProcess() as shown below:
Due to the fact that the CPU scheduler will assign a time quantum to each process, the parent orthe child process will run for some time before the control is switched to the other and the running
process will print some lines before you can see any line printed by the other process. Therefore,
the value ofMAX_COUNT should be large enough so that both processes will run for at least two
7/31/2019 System Calls Resources
8/15
or more time quanta. If the value ofMAX_COUNT is so small that a process can finish in one
time quantum, you will see two groups of lines, each of which contains all lines printed by the
same process
The getpid() system call returns the process ID of the calling process.Though the ID is guaranteed to be unique, it should NOT be used for con-
structing temporary file names, for security reasons; see mkstemp(3)instead.
The getppid() system call returns the process ID of the parent of thecalling process.
Open
open is a system call that is used to open a new file and obtain its file descriptor.
Function Definition
int open(const char *path, int oflags);int open(const char *path, int oflags, mode_t mode);
Field Description
const char*path
The relative or absolute path to the file that is to be opened.
int oflagsA bitwise 'or' separated list of values that determine the method in which the file is to beopened (whether it should be read only, read/write, whether it should be cleared whenopened, etc). See a list of legal values for this field at the end.
mode_t modeA bitwise 'or' separated list of values that determine the permissions of the file if it is created.See a list of legal values at the end.
return value
Returns the file descriptor for the new file. The file descriptor returned is always the smallest
integer greater than zero that is still available. If a negative value is returned, then there wasan error opening the file.
Code Snippet
Example using the open system call:
#include #include int main(){
size_t filedesc = open("testfile.txt", O_WRONLY | O_APPEND);
http://fuse4bsd.creo.hu/localcgi/?mkstemp+3http://codewiki.wikidot.com/system-callshttp://fuse4bsd.creo.hu/localcgi/?mkstemp+3http://codewiki.wikidot.com/system-calls7/31/2019 System Calls Resources
9/15
if(filedesc < 0) return1;
if(write(filedesc,"This will be output to testfile.txt\n", 36) != 36){
write(2,"There was an error writing to testfile.txt\n",43); return1;
}
return0;}
Available Values foroflag
Value Meaning
O_RDONLY Open the file so that it is read only.
O_WRONLY Open the file so that it is write only.
O_RDWR Open the file so that it can be read from and written to.
O_APPEND Append new information to the end of the file.
O_TRUNC Initially clear all data from the file.
O_CREATIf the file does not exist, create it. If the O_CREAT option is used, then you must include thethird parameter.
O_EXCLCombined with the O_CREAT option, it ensures that the caller must create the file. If the filealready exists, the call will fail.
Available Values formode
Value Meaning
S_IRUSR Set read rights for the owner to true.
S_IWUSR Set write rights for the owner to true.
S_IXUSR Set execution rights for the owner to true.
S_IRGRP Set read rights for the group to true.
S_IWGRP Set write rights for the group to true.
S_IXGRP Set execution rights for the group to true.
S_IROTH Set read rights for other users to true.
7/31/2019 System Calls Resources
10/15
S_IWOTH Set write rights for other users to true.
S_IXOTH Set execution rights for other users to true.
Close
close is asystem call that is used to close an open file descriptor.
Required Include Files
#include
Function Definition
int close(int fildes);
Field Description
int fildes The file descriptor to be closed.
return valueRetuns a 0 upon success, and a -1 upon failure. It is important to check the return value,
because some network errors are not returned until the file is closed.
Code Snippet
Example closing an open file descriptor:
#include #include int main(){
size_t filedesc = open("testfile.txt", O_WRONLY | O_CREAT); if(filedesc < 0) return1;
if(close(filedesc) < 0) return1;
return0;
}
Write
write is asystem call that is used to write data out of a buffer.
http://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/system-calls7/31/2019 System Calls Resources
11/15
Required Include Files
#include
Function Definition
size_t write(int fildes, const void *buf, size_t nbytes);
Field Description
int fildesThe file descriptor of where to write the output. You can either use a file descriptor obtainedfrom the open system call, or you can use 0, 1, or 2, to refer to standard input, standardoutput, or standard error, respectively.
const void*buf
A null terminated character string of the content to write.
size_t nbytes The number of bytes to write. If smaller than the provided buffer, the output is truncated.
return valueReturns the number of bytes that were written. If value is negative, then the system callreturned an error.
Code Snippet
Example using standard file descriptors:
#include int main(void)
{ if (write(1, "This will be output to standard out\n", 36) != 36) {write(2, "There was an error writing to standard out\n", 44);
return -1;}
return0;
}
Example using a file descriptor:
#include #include
int main(void){
int filedesc = open("testfile.txt", O_WRONLY | O_APPEND);
if (filedesc < 0) { return -1;
}
http://codewiki.wikidot.com/c:system-calls:openhttp://codewiki.wikidot.com/c:system-calls:open7/31/2019 System Calls Resources
12/15
if (write(filedesc, "This will be output to testfile.txt\n", 36) != 36) {write(2, "There was an error writing to testfile.txt\n", 43);
return -1;}
return0;
}
Read
read is a system call used to read data into a buffer.
Required Include Files
#include
Function Definition
size_t read(int fildes, void *buf, size_t nbytes);
Field Description
int fildesThe file descriptor of where to write the output. You can either use a file descriptor obtainedfrom the open system call, or you can use 0, 1, or 2, to refer to standard input, standardoutput, or standard error, respectively.
const void*buf
A character array where the read content will be stored.
size_t nbytesThe number of bytes to read before truncating the data. If the data to be read is smaller thannbytes, all data is saved in the buffer.
return valueReturns the number of bytes that were read. If value is negative, then the system callreturned an error.
Code Snippet
#include int main()
{char data[128];
if(read(0, data, 128) < 0)
write(2, "An error occurred in the read.\n", 31);
exit(0);}
http://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/c:system-calls:openhttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/c:system-calls:open7/31/2019 System Calls Resources
13/15
Stat
stat is a system call that is used to determine information about a file based on its file path.
Required Include Files#include #include #include
Function Definition
int stat(const char *path, struct stat *buf);
Field Description
const char*path The file descriptor of the file that is being inquired.
struct stat *bufA structure where data about the file will be stored. A detailed look at all of the fields in thisstructure can be found in the struct stat page.
return value Returns a negative value on failure.
Code Snippet
An example of code that uses the stat() system call is below.
#include #include #include #include int main(int argc, char **argv){ if(argc != 2)
return1;
struct stat fileStat; if(stat(argv[1],&fileStat) < 0)
return1;
printf("Information for %s\n",argv[1]);printf("---------------------------\n");printf("File Size: \t\t%d bytes\n",fileStat.st_size);printf("Number of Links: \t%d\n",fileStat.st_nlink);printf("File inode: \t\t%d\n",fileStat.st_ino);
printf("File Permissions: \t");printf( (S_ISDIR(fileStat.st_mode)) ? "d" : "-");
http://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/c:struct-stathttp://codewiki.wikidot.com/system-callshttp://codewiki.wikidot.com/c:struct-stat7/31/2019 System Calls Resources
14/15
printf( (fileStat.st_mode & S_IRUSR) ? "r" : "-");printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");printf( (fileStat.st_mode & S_IXOTH) ? "x" : "-");printf("\n\n");
printf("The file %s a symbolic link\n", (S_ISLNK(fileStat.st_mode)) ? "is"
: "is not");
return0;}
The output of this program is shown in the following set of commands:
Information on the current files in the directory:
$ ls -ltotal 16-rwxr-xr-x 1 stargazer stargazer 36 2008-05-06 20:50 testfile.sh-rwxr-xr-x 1 stargazer stargazer 7780 2008-05-07 12:36 testProgram-rw-r--r-- 1 stargazer stargazer 1229 2008-05-07 12:04 testProgram.c
Running the program with the file testfile.sh
$ ./testProgram testfile.sh
Information for testfile.sh---------------------------File Size: 36 bytesNumber of Links: 1File inode: 180055File Permissions: -rwxr-xr-x
The file is not a symbolic link
Running the program with the files testProgram.c
$ ./testProgram testProgram.c
Information for testProgram.c---------------------------File Size: 1229 bytesNumber of Links: 1File inode: 295487File Permissions: -rw-r--r--
The file is not a symbolic link
7/31/2019 System Calls Resources
15/15
Running the program with the directory /home/stargazer
$ ./testProgram /home/stargazer
Information for /home/stargazer---------------------------
File Size: 4096 bytesNumber of Links: 61File inode: 32706File Permissions: drwxr-xr-x
The file is not a symbolic link
wait():
The parent process will often want to wait until all child processes have been
completed. this can be implemented with the wait() function call.
wait(): Blocks calling process until the child process terminates. If child process has
already teminated, the wait() call returns immediately. if the calling process has multiple
child processes, the function returns when one returns