#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    75
    Rep Power
    2

    System Calls in C


    I don't understand what do you mean by system calls. It says they are functions that interact with the operating system.
    But every command/instruction in C will interact with the operating system, right?

    Even the simple: - int i; will require an operating system to allocate 4 bytes in memory. So basically every instruction interacts with the OS. So what are system calls?
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2013
    Location
    India
    Posts
    95
    Rep Power
    4
    by using system call u can directly communicate with OS.
    normal C function internally uses system call to interact with OS.

    for example fopen function uses open system call.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    75
    Rep Power
    2
    Originally Posted by eramit2010
    by using system call u can directly communicate with OS.
    normal C function internally uses system call to interact with OS.

    for example fopen function uses open system call.
    I don't get you. My query is that: to me it seems that all C functions or instructions are system calls. For e.g.: - When you declare a variable it calls the OS to allocate some memory to a variable. When you open a file it calls the OS to look for the file in the memory etc.
    So everything is a system call! But apparently it isn't. Why?
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Wrong!

    When you declare a variable, the OS does not get involved! For one thing, that's a compile time operation, so it's the compiler that either sets aside the space in the static segment (for globals) or generates the thunk code to set up the stack frame to include that variable (for locals). At run time, the OS does allocate a block of RAM to the program when it loads in preparation for execution, but then when the program is running, it is the program's own code, not the OS, that runs that thunk code to create the local variable on the stack.

    When you call a standard library function, you are not making a system call, because that library function has been linked in to your program. A library function might make a system call, but it is not a system call in itself.

    The OS runs privileged code and has privileged access to resources that your program does not have privileges for. This protects the system and other processes from your program. To make use of those resources or services, you use a system call to make a request to the OS. Inside that system call function is special code that's needed to perform the actual communication with the OS; your program cannot do that directly.

    Instructions being run by your program are not "system calls" (for that matter, even instructions being run by the OS itself are not system calls). Your own functions in your own program are not system calls. Standard C library functions are not system calls. Only system calls, functions that directly request something from the OS, are system calls.

    For one thing, system calls are specific to that OS. UNIX and Linux system calls are different from Windows 32 system calls are different from system calls under other OSes. If every C program had to directly handle communicating with the OS, then you would have to rewrite every program every time you ported it to a different OS. Instead, the standard C library functions all appear the same in all compilers on all platforms, even though the actual code behind the functions are different in order to work with that specific OS. That way, you don't need to rewrite your program in order to do I/O on different platforms. At the same time, if your program uses systems calls, then that part of your program will need to be rewritten (eg, you can fork and set up IPC under UNIX/Linux, but that code won't work under Windows which has different system calls).

    When you open a file it calls the OS to look for the file in the memory etc.
    fopen is not a system call, but rather a standard library function. It does make system calls, but it is not a system call itself.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    75
    Rep Power
    2
    So is it right to say that functions that cause an interrupt in the running program are system calls?
    Can you give me some examples for system calls? Most of them I knew, you tell me they aren't.

    Thank You for the excellent post, BTW.
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    OK, time to get technical about it. Terminology can be used strictly or loosely. For example, a compiler is a program that performs a very specific job, which is to parse a source file and translate it into an object file. Strictly speaking, that's all that a compiler does; it doesn't even create an executable file, since that is the job of the linker. And, strictly speaking, an integrated development environment (IDE) incorporates a text editor, compiler, linker, debugger, etc, into one application. And yet, loosely speaking, just about everybody refers to their IDE as their "compiler".

    And, strictly speaking, a system call is the actual sending of a request to OS, normally via an interrupt, that switches the computer from user mode to protected mode. The "system call" function call that you make (eg, calling fork()) does not itself constitute a system call, but rather that function that you call via the normal function call mechanism will then cause to set up the actual system call via the system's system call mechanism (eg, an interrupt). However, loosely speaking we refer to such functions themselves as "system calls" since that is their explicit purpose and because they are specific and peculiar to the OS.

    Back in the MS-DOS days, we used to write the actual system calls. I worked with Turbo Pascal and Borland C++ in those days and both languages were extended with structs representing the CPU registers and calls to generate an interrupt, plus functions to read and set interrupt vectors in the Interrupt Vector Table (MS-DOS was wide open, which is why it was so prone to crashing). MS-DOS calls were made via Int 21H (21 hex) -- ROM-BIOS calls used other interrupts, plus Int 20H was Terminate Process. Under Int 21H was a long list of functions. So you would load the register struct with the parameters you were passing via the interrupt, then you would call the interrupt and when it returned you would read the register struct for the results.

    For example, to read a disk directory you would use two functions: Find First File (11H) and Find Next File (12H). You would pass Find First File the address of a file control block struct (in register DS:DX) and that system call would return in register AL an indication of success or failure; upon success, the file control block would be filled with the data you requested. Then you would loop making successive calls to Find Next File, processing each file in turn, until that function returned failure.

    That was the actual system calls that we would perform. Actually, the first compilers that Microsoft released for the IBM PC had no built-in support to make the system calls for you, so you had to write your own system call routines yourself using the method I just described. But then the compilers started providing functions that would perform the system calls for you, such that hardly anyone has to write an actual system call anymore. And these functions were modeled after the system calls that they would invoke, such that you have the functions _findfirst() and _findnext(). Even in Win32, you still have the functions FindFirstFile() and FindNextFile(). Loosely speaking, we would refer to calling those functions as "making a system call", even though that would not be strictly correct.

    To see what the "system call" functions are, look in the header files. For example, MinGW's gcc port's dos.h file #include's io.h, which lists:
    Code:
    int	_findfirst (const char*, struct _finddata_t*);
    int	_findnext (int, struct _finddata_t*);
    int	_findclose (int);
    
    int	_chdir (const char*);
    char*	_getcwd (char*, int);
    int	_mkdir (const char*);
    char*	_mktemp (char*);
    int	_rmdir (const char*);
    
    
    #ifdef __MSVCRT__
    __int64  _filelengthi64(int);
    long _findfirsti64(const char*, struct _finddatai64_t*);
    int _findnexti64(long, struct _finddatai64_t*);
    __int64  _lseeki64(int, __int64, int);
    __int64  _telli64(int);
    #endif /* __MSVCRT__ */
    
    
    #ifndef _NO_OLDNAMES
    
    #ifndef _UWIN
    int	chdir (const char*);
    char*	getcwd (char*, int);
    int	mkdir (const char*);
    char*	mktemp (char*);
    int	rmdir (const char*);
    #endif /* _UWIN */
    
    #endif /* Not _NO_OLDNAMES */
    
    #ifdef	__cplusplus
    }
    #endif
    
    #endif	/* Not RC_INVOKED */
    
    #endif	/* Not __STRICT_ANSI__ */
    
    /* TODO: Maximum number of open handles has not been tested, I just set
     * it the same as FOPEN_MAX. */
    #define	HANDLE_MAX	FOPEN_MAX
    
    
    /* Some defines for _access nAccessMode (MS doesn't define them, but
     * it doesn't seem to hurt to add them). */
    #define	F_OK	0	/* Check for file existence */
    #define	X_OK	1	/* Check for execute permission. */
    #define	W_OK	2	/* Check for write permission */
    #define	R_OK	4	/* Check for read permission */
    
    #ifndef RC_INVOKED
    
    #ifdef	__cplusplus
    extern "C" {
    #endif
    
    int		_access (const char*, int);
    int		_chsize (int, long);
    int		_close (int);
    int		_commit(int);
    
    /* NOTE: The only significant bit in unPermissions appears to be bit 7 (0x80),
     *       the "owner write permission" bit (on FAT). */
    int		_creat (const char*, unsigned);
    
    int		_dup (int);
    int		_dup2 (int, int);
    long		_filelength (int);
    int		_fileno (FILE*);
    long		_get_osfhandle (int);
    int		_isatty (int);
    
    /* In a very odd turn of events this function is excluded from those
     * files which define _STREAM_COMPAT. This is required in order to
     * build GNU libio because of a conflict with _eof in streambuf.h
     * line 107. Actually I might just be able to change the name of
     * the enum member in streambuf.h... we'll see. TODO */
    #ifndef	_STREAM_COMPAT
    int		_eof (int);
    #endif
    
    /* LK_... locking commands defined in sys/locking.h. */
    int		_locking (int, int, long);
    
    long		_lseek (int, long, int);
    
    /* Optional third argument is unsigned unPermissions. */
    int		_open (const char*, int, ...);
    
    int		_open_osfhandle (long, int);
    int		_pipe (int *, unsigned int, int);
    int		_read (int, void*, unsigned int);
    
    /* SH_... flags for nShFlags defined in share.h
     * Optional fourth argument is unsigned unPermissions */
    int		_sopen (const char*, int, int, ...);
    
    long		_tell (int);
    /* Should umask be in sys/stat.h and/or sys/types.h instead? */
    int		_umask (int);
    int		_unlink (const char*);
    int		_write (int, const void*, unsigned int);
    
    
    #ifndef	_NO_OLDNAMES
    /*
     * Non-underscored versions of non-ANSI functions to improve portability.
     * These functions live in libmoldname.a.
     */
    
    #ifndef _UWIN
    int		access (const char*, int);
    int		chsize (int, long );
    int		close (int);
    int		creat (const char*, int);
    int		dup (int);
    int		dup2 (int, int);
    int		eof (int);
    long		filelength (int);
    int		fileno (FILE*);
    int		isatty (int);
    long		lseek (int, long, int);
    int		open (const char*, int, ...);
    int		read (int, void*, unsigned int);
    int		sopen (const char*, int, int, ...);
    long		tell (int);
    int		umask (int);
    int		unlink (const char*);
    int		write (int, const void*, unsigned int);
    #endif /* _UWIN */
    What you'll notice there is some cross-over from Linux, since MinGW gcc is a port from Linux to Windows. For example, under Linux you would not use the MS-DOS approach of _findfirst/_findnext, but rather you would read a directory as if it were a file. So from dir.h you have opendir and readdir. MinGW provides you with that approach within your program, but you can bet that under the hood it's making the same Find First File and Find Next File system calls that _findfirst and _findnext do.

    I hope that made sense.

    If you're using Linux, then look in unistd.h for the UNIX standard functions that most would refer to as "system calls". For that matter, there should be a sys directory under the compiler's include directory (which houses the header files) which has other header files of "system call" functions.

    PS

    You might want to read the System call article in Wikipedia at http://en.wikipedia.org/wiki/System_call. The links at the bottom include lists of system calls.
    Last edited by dwise1_aol; August 1st, 2013 at 02:53 PM.
  12. #7
  13. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    Originally Posted by Avichal
    So is it right to say that functions that cause an interrupt in the running program are system calls?
    Can you give me some examples for system calls? Most of them I knew, you tell me they aren't.

    Thank You for the excellent post, BTW.
    Some functions are thin wrappers to OS level functions that do specific things (e.g.) open(), close(), chown(), chmod(), read() etc. Some other functions do not need OS help at all (e.g.) sqrt(), sin(), cos() etc. Some other functions call OS functions as part of doing their work, but do a lot of their work without involving the OS much (e.g.) fopen(), which does a lot of stuff and calls open() within itself somewhere, fclose() calls close() somewhere within it, printf(), which calls write() somewhere within it etc.

    In *nix, the convention is that all system functions are in section 2 of the manual and user level functions are in section 3. So, if you do this:
    Code:
    man close
    the first line of the man page looks like this:
    Code:
    CLOSE(2)                   Linux Programmer's Manual                  CLOSE(2)
    The "(2)" indicates this is from section 2 (i.e. system calls). Similarly, if you type man fopen, you'll see:
    Code:
    FOPEN(3)                   Linux Programmer's Manual                  FOPEN(3)
    As you can see, fopen is in section 3 of the manual.

    In some cases, you'll need to pass the specific section into the man command. For example, printf is not only a C function, but also a shell command. So if you type "man printf", it will print the documentation from section 1 of the manual (i.e. the shell command). If you want help about the C function, you should type "man 3 printf".

    Most library functions are portable across different OSs, not so much for system functions..
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  14. #8
  15. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,111
    Rep Power
    1803
    The OS provides services, a function call that provides that service is a system call. A function that calls a system call is not itself a system call.

    The ability of call functions and read/write memory is intrinsic to computing hardware and not a system service, so that vast majority of the C standard library for example has no system dependencies whatsoever. Those that do are those related to dynamic memory management and I/O, but even then are not themselves system calls - though they will be implemented using system calls.

    Essentially a system call invokes a service that is provided by the operating system rather than part of your program. The distinction is blurred perhaps by DLLs and shared libraries, since most system calls in Windows, Linux, and OSX for example are provided by "system" DLLs or libraries, that may not be easily distinguishable from any other library and there are layers of core and optional libraries in large modern operating systems.

    In the end does it matter much?

IMN logo majestic logo threadwatch logo seochat tools logo