3
votes

I have been reading about system calls and how they work in Linux. I still have more reading to do but one thing that nothing I have read has answered is, WHY do we need system calls?

I understand that system calls are requests from user space program for the kernel to do something, but my question is basically: Why can't the user space program do the thing itself? Why doesn't Glibc do the actual operation instead of just being a wrapper for a system call?

For example, if I call fopen() in my program, why does glibc call the open system call? Why doesn't glibc just do the operation itself?

I understand that it would mean that glibc developers would have a lot more work and that they would have to have an intimate knowledge of Linux, but isn't glibc already very closely related to Linux kernel?

Also, I understand the system call functions are run in ring 0 in the CPU...but what's really the point of that? If I execute a program, I am giving it express permission to run, so what security is added by separating what code can be run in different contexts since you are giving it all permission anyway?

7
Why can't the user space program do the thing itself - it could. In DOS. Then people realized they need to protect some stuff from being accessed by anyone for the greater good.Eugene Sh.
Because the OS (i.e. the linux kernel) has to manage hardware resources and coordinating other user programs also making requests - so it has to have that authority. If individual programs just did what they liked you'd be back in the dark days of DOSauburg
Recall that one of the primary jobs is to provide security and stability for the system. It can't do that if any old userspace program has the ability to do whatever it wants. Hence, the interface for userspace to the kernel exists, so the kernel can be sure the program is only able to do things it's allowed to do.Jonathon Reinhart
"Why doesn't Glibc do the actual operation instead of just being a wrapper for a system call?" Why don't you push this a bit further? Why doesn't the programmer do the operation itself instead of using <enter your favorite lib here>?Gerhardh
Read Operating Systems: Three Easy Pieces since an entire book is needed to answer your questionBasile Starynkevitch

7 Answers

11
votes

Why doesn't glibc just do the operation itself?

Well that is more less the ways things went in good old MS/DOS systems: no separation between kernel code and user code, and user code could happily directly access the hardware.

This just has 2 major problems:

  • It works (rather) fine on a single user and not multi tasking system, but as soon as multiple programs can simultaneously run in a system, you have to synchronize hardware accesses and memory usage => those are the parts dedicated to the kernel
  • There is no protection of the system from a poorly coded program. In a modern OS, an erroneous program can crash, but the system itself should survive. In MS/DOS a program crash usually ended in a system reboot.

For those reasons, all modern OS (except maybe some lightweight embedded ones) use isolation between different user processes and the kernel. And that just mean that you need a way to allow a user mode process to require a privileged action (reading or writing a physical disk is) from the kernel: that is exactly what system calls are made for.

2
votes

Why doesn't glibc just do the operation itself?

Short answer: Because it can't.


Long answer: A program running in Linux can run in two modes : UserLand or KernelLand.

The Kernel Land has every rights and can do everything, including talking with hardware, or providing userspace callbacks. For instance, when you call fopen(), the kernel does all the dirty talking with your filesystem (ext4 for instance), the caching, everything down to talking with the SATA Controller to access data on the hard-drive.

GLibc could do that using the device exposed by the kernel in /dev, but that would mean recoding from scratch all the filesystems layers, the sockets, the firewalling...

The kernel just provides easy usable API for programmers to have elevated rights and communicate with the devices. That's how Linux (and most modern OS) is made.

What security is added by separating what code can be run in different contexts since you are giving it all permission anyway?

The permissions are managed by the kernel. If you don't have syscall, you don't have permissions. Or should the program you run check their own permission? Once again, it would be reinventing the wheel every time.

1
votes

If the code generated by a C implementation were the only thing that were going to be running on the target system (as it would be for many freestanding implementations, and for a very small number of hosted implementations) and if implementation knew precisely what hardware it would be running upon (true of some freestanding implementations, but seldom true for hosted ones), its runtime library might be able to perform operations like "fopen" by directly communicating with the storage hardware. It is rare, however, for either condition to apply, much less both of them.

If multiple programs will be using storage device, it will generally be necessary that they either coordinate their actions somehow or else that sequences of operations performed by different programs do not overlap, and that every program "forget" anything it thinks it knows about the state of storage any time another program might have written to it.

Otherwise, suppose a disk contains a single file and program #1 uses "fopen" to open it for reading. Each directory sector holds 8 entries, so the program would read the first directory sector and observe that slot #0 identifies the file of interest while #1-#7 are blank.

Now suppose program #2 uses "fopen" to create a file for writing. It would read the directory sector, observe that slots #1-#7 are blank, and rewrite the directory sector with information about the new file in slot #1.

Finally, suppose program #1 wants to write a file. If it doesn't know about program #2, it might reasonably believe it knows what the directory contains (it had read it earlier, and has no reason to believe it's changed), place information about the new file in slot #1, and replace the directory sector on disk with its new version, obliterating the entry written by program #2.

Having both programs route their operations through an operating system ensures that when program #2 wants to create its file, it can exploit the fact that it had just read the directory for program #1 (and thus doesn't need to reread it). More importantly, when program #1 goes to write a file, the operating system will know that the directory contains the file written by program #2, and will thus ensure that the new file gets placed in slot #2.

Contrary to what other answers say, even microcomputer C implementations running on platforms like MS-DOS essentially always relied upon the OS for file I/O. Some would include their own console I/O routines because the ones in MS-DOS were about four times as slow as they should have been, but the need for coordination when using file I/O meant that very few programs would try to do it themselves.

1
votes

1- You don't wanna deal with low-level hardware communications. At least most people don't. Each of them has hundreds of commands.

2- Make a simple mistake and your CPU/RAM or I/O device might be useless forever.

3- When you are part of a network, you can share resources. The system calls and kernel keeps your co-worker from damaging your hard disk.

0
votes

Another consideration is that the OS kernel needs to provide an abstraction for the myriad different types of hardware via a uniform API - without which you'd invariably be making device specific calls in your program.

0
votes

While the previously-idle disk spins up for two seconds, or the networked disk gets connected for thirty seconds, what is the library going to do?

0
votes

The full answer to your question is very broad but let me take a simple example based upon your question about fopen.

Let us say that we have a large system that has hundred or thousands of users. One of those users is, say the HR department with files containing confidential information about employees.

If that disk could be accessed at will in user mode, then any person on the system could open any file on the system, including those with confidential information.

In other words operating systems managed SHARED resources. These include disk, CPU, and memory. If these could be controlled in user mode, there would be no way to ensure that these were shared equitably.