Sei sulla pagina 1di 14

Introduction of System Call

In computing, a system call is the programmatic way in which a computer program requests a
service from the kernel of the operating system it is executed on. A system call is a way for
programs to interact with the operating system. A computer program makes a system call when it
makes a request to the operating system’s kernel. System call provides the services of the operating
system to the user programs via Application Program Interface(API). It provides an interface
between a process and operating system to allow user-level processes to request services of the
operating system. System calls are the only entry points into the kernel system. All programs
needing resources must use system calls.

A system call is just what its name implies -- a request for the operating system to do something on
behalf of the user's program. The system calls are functions used in the kernel itself. To the
programmer, the system call appears as a normal C function call.

However since a system call executes code in the kernel, there must be a mechanism to change the
mode of a process from user mode to kernel mode.

The C compiler uses a predefined library of functions (the C library) that have the names of the
system calls. The library functions
typically invoke an instruction that changes the process execution mode to kernel mode and causes
the kernel to start executing code for systemcalls. The instruction that causes the mode change is
often referred to as an "operating system trap" which is a software generated interrupt.
The library routines execute in user mode, but the system call interface is a special case of an
interrupt handler.

The library functions pass the kernel a unique number per system call in a machine dependent way
--either as a parameter to the operating system trap, in a particular
register, or on the stack -- and the kernel thus determines the specific system call the user is
invoking. In handling the operating system trap, the kernel looks up the system call number in a
table to find the address of the appropriate kernel routine that is the entry point for the system call
and to find the number of parameters the system call expects. The kernel calculates the (user)
address of the first parameter to the system call by adding (or subtracting, depending on the
direction of stack growth) an offset to the user stack pointer, corresponding to the number of the
parameters to the system call. Finally, it copies the user parameters to the "u area" and call the
appropriate system call routine.

After executing the code for the system call, the kernel determines whether there was an error. If
so, it adjusts register locations in the saved user register context, typically setting the "carry" bit for
the PS (processor status) register and copying the error number into register 0 location. If there
were no errors in the execution of the system call, the kernel clears the "carry" bit in the PS register
and copies the appropriate return values from the system call into the locations for registers 0 and 1
in the saved user register context. When the kernel returns from the operating system trap to user
mode, it returns to the library instruction after the trap instruction. The library interprets the return
values from the kernel and returns a value to the user program.

UNIX system calls are used to manage the file system, control processes, and to provide
interprocess communication. The UNIX system interface consists of about 80 system calls (as
UNIX evolves this number will increase). The following table lists about 40 of the more important
system call:

GENERAL CLASS SPECIFIC CLASS SYSTEM CALL


---------------------------------------------------------------------
File Structure Creating a Channel creat()
Related Calls open()
close()
Input/Output read()
write()
Random Access lseek()
Channel Duplication dup()
Aliasing and Removing link()
Files unlink()
File Status stat()
fstat()
Access Control access()
chmod()
chown()
umask()
Device Control ioctl()
---------------------------------------------------------------------
Process Related Process Creation and exec()
Calls Termination fork()
wait()
exit()
Process Owner and Group getuid()
geteuid()
getgid()
getegid()
Process Identity getpid()
getppid()
Process Control signal()
kill()
alarm()
Change Working Directory chdir()
----------------------------------------------------------------------
Interprocess Pipelines pipe()
Communication Messages msgget()
msgsnd()
msgrcv()
msgctl()
Semaphores semget()
semop()
Shared Memory shmget()
shmat()
shmdt()
----------------------------------------------------------------------

What is the File Descriptor??


File descriptor is integer that uniquely identifies an open file of the process.

File Descriptor table: File descriptor table is the collection of integer array indices that are file
descriptors in which elements are pointers to file table entries. One unique file
descriptors table is provided in operating system for each process.

File Table Entry: File table entries is a structure In-memory surrogate for an open file, which is
created when process request to opens file and these entries maintains file position.
Standard File Descriptors: When any process starts, then that process file descriptors table’s fd(file
descriptor) 0, 1, 2 open automatically, (By default) each of these 3 fd references file table entry for a
file named /dev/tty
/dev/tty: In-memory surrogate for the terminal
Terminal: Combination keyboard/video screen

Read from stdin => read from fd 0 : Whenever we write any character from keyboard, it read
from stdin through fd 0 and save to file named /dev/tty.
Write to stdout => write to fd 1 : Whenever we see any output to the video screen, it’s from the
file named /dev/tty and written to stdout in screen through fd 1.
Write to stderr => write to fd 2 : We see any error to the video screen, it is also from that file write
to stderr in screen through fd 2.
I/O System calls
Create() : Used to create a new empty file.

Syntax in C language:
int create(char *filename, mode_t mode)

Parameter :
 filename : name of the file which you want to create
 mode : indicates permissions of new file.

Returns :
 return first unused file descriptor (generally 3 when first creat use in process beacuse 0, 1,
2 fd are reserved)
 return -1 when error

How it work in OS
 Create new empty file on disk
 Create file table entry
 Set first unused file descriptor to point to file table entry
 Return file descriptor used, -1 upon failure

Example:

C program for create system call


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>

int main(int argc,char **argv)


{
int fd;
fd = creat("argv[1]", S_IREAD | S_IWRITE);
if (fd == -1)
{
perror("Error:");
printf("Error in opening file\n");
}
else
{
printf("file opened for read/write access\n");
printf("file currently empty\n");
}
return 0;
}
Perror :
When a system call discovers and error, it returns -1 and stores the reason the called failed in an
external variable named "errno". Th "/usr/include/errno.h" file maps these error numbers to
manifest constants, and it these constants that you should use in your programs.

When a system call returns successfully, it returns something other than -1, but it does not clear
"errno". "errno" only has meaning directly after a system call that returns an error.

When you use system calls in your programs, you should check the value returned by those system
calls. Furthermore, when a system call discovers an error, you should use the "perror()" subroutine
to print a diagnostic message on the standard error file that describes why the system call failed.
The syntax for "perror()" is:

void perror(string)
char string;

"perror()" displays the argument string, a colon, and then the error message, as directed by "errno",
followed by a newline. The output of "perror()" is displayed on "standard error". Typically, the
argument give to "perror()" is the name of the program that incurred the error,argv[0]. However,
when using subroutines and system calls on files, the related file name might be passed to
"perror()".

There are occasions where you the programmer might wish to maintain more control over the
printing of error messages than "perror()" provides -- such as with a formatted screen where the
newline printed by "perror()" would destroy the formatting. In this case, you can directly access the
same system external (global) variables that "perror()" uses. They are:

extern int errno;


extern char *sys_errlist[];
extern int sys_nerr;

Example:

C program for perror messages in kernal


#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>

int main()
{
int i;
extern int errno, sys_nerr;

for (i = 0; i < sys_nerr; ++i)


{
fprintf(stderr, "%3d",i);
errno = i;
perror(" ");
}
exit (0);
}
open() :

Used to Open the file for reading, writing or both.


Syntax in C language
#include<sys/types.h>
#includ<sys/stat.h>
#include <fcntl.h>
int open (const char* Path, int flags [, int mode ]);
Parameters
 Path : path to file which you want to use
 use absolute path begin with “/”, when you are not work in same directory of file.
 Use relative path which is only file name with extension, when you are work in same
directory of file.
 flags : How you like to use
 O_RDONLY: read only,
 O_WRONLY: write only,
 O_RDWR: read and write,
 O_CREAT: create file if it doesn’t exist,
 O_EXCL: prevent creation if it already exists

How it works in OS
 Find existing file on disk
 Create file table entry
 Set first unused file descriptor to point to file table entry
 Return file descriptor used, -1 upon failure

Example
C program for open system call
#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
extern int errno;
int main()
{
// if file does not have in directory
// then file foo.txt is created.

int fd = open("abc.txt",O_WRONLY);

printf("fd = %d/n", fd);

if (fd ==-1)
{
// print which type of error have in a code
printf("Error Number % d\n", errno);
// print program detail "Success or failure"
perror("Program");
}
return 0;
}
close();
Tells the operating system you are done with a file descriptor and Close the file which pointed by
fd.

Syntax in C language
#include <fcntl.h>
int close(int fd);
Parameter
 fd :file descriptor
Return
 0 on success.
 -1 on error.
How it works in the OS
 Destroy file table entry referenced by element fd of file descriptor table
– As long as no other process is pointing to it!
 Set element fd of file descriptor table to NULL

Example
C program for close system call
#include<stdio.h>
#include <fcntl.h>
int main()
{
int fd1 = open("abc.txt", O_RDONLY);
if (fd1 < 0)
{
perror("c1");
exit(1);
}
printf("opened the fd = % d\n", fd1);

// Using close system Call


if (close(fd1) < 0)
{
perror("c1");
exit(1);
}
printf("closed the fd.\n");
}

read();
From the file indicated by the file descriptor fd, the read() function reads cnt bytes of input into the
memory area indicated by buf. A successful read() updates the access time for the file.
Syntax in C language
size_t read (int fd, void* buf, size_t cnt);
Parameters
 fd: file descripter
 buf: buffer to read data from
 cnt: length of buffer
Returns: How many bytes were actually read
 return Number of bytes read on success
 return 0 on reaching end of file
 return -1 on error
 return -1 on signal interrupt
Important points
 buf needs to point to a valid memory location with length not smaller than the specified size
because of overflow.
 fd should be a valid file descriptor returned from open() to perform read operation because
if fd is NULL then read should generate error.
 cnt is the requested number of bytes read, while the return value is the actual number of
bytes read. Also, some times read system call should read less bytes than cnt.

Example
C program for read system call
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>

int main(int argc,char **argv)


{
char buf[10];
int n,fd1,fd2;

fd1=open(argv[1],O_RDWR);
if(fd1==-1)
{
perror("Error");
printf("unalbe to open file\n");
}
else
{
printf("file opend sucessfully..\n");
}
fd2=open(argv[2],O_RDWR);
if(fd2==-1)
{
perror("Error");
printf("unalbe to open file\n");
}
else
{
printf("file opend sucessfully..\n");
}
while ((n = read(fd1, buf, 10)) > 0)
write(fd2, buf, n);
return 0;
}

write();
Writes cnt bytes from buf to the file or socket associated with fd. cnt should not be greater than
INT_MAX (defined in the limits.h header file). If cnt is zero, write() simply returns 0 without
attempting any other action.

#include <fcntl.h>
size_t write (int fd, void* buf, size_t cnt);

Parameters
 fd: file descripter
 buf: buffer to write data to
 cnt: length of buffer

Returns: How many bytes were actually written


 return Number of bytes written on success
 return 0 on reaching end of file
 return -1 on error
 return -1 on signal interrupt

Important points
 The file needs to be opened for write operations
 buf needs to be at least as long as specified by cnt because if buf size less than the cnt then
buf will lead to the overflow condition.
 cnt is the requested number of bytes to write, while the return value is the actual number of
bytes written. This happens when fd have a less number of bytes to write than cnt.
 If write() is interrupted by a signal, the effect is one of the following:
-If write() has not written any data yet, it returns -1 and sets errno to EINTR.
-If write() has successfully written some data, it returns the number of bytes it wrote
before it was interrupted.

Example
C program for write system call
#include<stdio.h>
#include<sys/stat.h>
#include<errno.h>
#include <fcntl.h>
main()
{
int sz;

int fd = open("abc.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);


if (fd < 0)
{
perror("r1");
exit(1);
}

sz = write(fd, "hello friends \n", strlen("Sample unix class \n"));

printf("called write(% d, \"Sample unix class\\n\", %d)."


" It returned %d\n", fd, strlen("Sample unix class\n"), sz);

close(fd);
}

(or)

#include < string.h >


#include < unistd.h >
#include < fcntl.h >

int main (void)


{
int fd[2];
char buf1[12] = "just a test";
char buf2[12];

fd[0] = open("tfile",O_RDWR);
fd[1] = open("tfile",O_RDWR);

write(fd[0],buf1,strlen(buf1));
write(1, buf2, read(fd[1],buf2,12));

close(fd[0]);
close(fd[1]);

return 0;
}

rename();
C program for rename system call (mv command)
#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<errno.h>

int main(int argc,char **argv)


{
rename(argv[1],argv[2]);
return (0);
}

C program for Cat command


#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
int fd,i;
char ch[1];
if(argc<2)
{
printf("usage:mycat filename\n");
exit(0);
}
fd=open(argv[1],O_RDONLY);
if(fd==-1)
printf("%s is not exist",argv[1]);
else
{
printf("contents of the file %s is:\n",argv[1]);
while(read(fd,ch,1)>0)
printf("%c",ch[0]);
close(fd);
}
return 0;
}

C program for copy system call (copy command)


#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
extern int errno;
int main()

{
int fd1,fd2;
char buf[1024];
long int n;
fd1=open("new.txt",O_RDWR);
if(fd1==-1){
perror("Error:");
printf("unable to open file");
exit(1);
}
else
{
printf("file opened sucessfully with fd=%d",fd1);
}

fd2=creat("new6.txt",S_IRWXU|S_IRGRP|S_IROTH);
if(fd2==-1)
{
perror("Error:");
printf("unable to create file");
exit(2);
}
else
{
printf("file created sucessfully with fd=%d",fd2);
}
while((n=read(fd1,buf,1024))>0){
if(write(fd2,buf,n)!=n){
perror("Error");
printf("unable to write data in to second file");
}

}
return 0;
}

C program for lseek system call

#include <stdio.h>
#include <fcntl.h>

int main()
{
int fd;
long position;

fd = open("datafile.dat", O_RDONLY);
if ( fd != -1)
{
position = lseek(fd, 0L, 2); /* seek 0 bytes from end-of-file */
if (position != -1)
printf("The length of datafile.dat is %ld bytes.\n", position);
else
perror("lseek error");
}
else
printf("can't open datafile.dat\n");
close(fd);
}

C program to illustrate I/O system calls

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>

int main (void)


{
int fd[2];
char buf1[12] = "hello world";
char buf2[12];

// assume foobar.txt is already created


fd[0] = open("foobar.txt", O_RDWR);
fd[1] = open("foobar.txt", O_RDWR);

write(fd[0], buf1, strlen(buf1));


write(1, buf2, read(fd[1], buf2, 12));

close(fd[0]);
close(fd[1]);

return 0;
}

C program for link system call


#include<stdio.h>
#include<fcntl.h>
#include<errno.h>

extern int errno;


int main(int argc,char **argv[])
{

int fd = link(argv[1],argv[2]);

printf("fd = %d/n", fd);

if (fd ==-1)
{
// print which type of error have in a code
printf("Error Number % d\n", errno);

// print program detail "Success or failure"


perror("Program");
}
return 0;
}

Output:
aditya@CSE-WEB:~$ ./a.out x2 x1
fd = 0/naditya@CSE-WEB:~$ ls -li x2 x1
19011963 -rw-rw-r-- 2 aditya aditya 6 Sep 7 14:44 x1
19011963 -rw-rw-r-- 2 aditya aditya 6 Sep 7 14:44 x2

C program for unlink system call


#include<stdio.h>
#include<fcntl.h>
#include<errno.h>
extern int errno;
int main(int argc,char **argv[])
{
int fd = unlink(argv[1]);

printf("fd = %d/n", fd);

if (fd ==-1)
{
// print which type of error have in a code
printf("Error Number % d\n", errno);

// print program detail "Success or failure"


perror("Program");
}
return 0;
}
Output:
aditya@CSE-WEB:~$ ./a.out x1
fd = 0/naditya@CSE-WEB:~$ ls -li x1 x2
ls: cannot access 'x1': No such file or directory
19011963 -rw-rw-r-- 1 aditya aditya 6 Sep 7 14:44 x2

C program for link system call

Potrebbero piacerti anche