C Language: Runtime Library Standards & Operating Systems

In summary: It's not a system call library, it's just a header that declares available system calls and provides your program with ways to execute them. The library itself is probably called...something like "unistd".
  • #1
RedX
970
3
Is it true that the the makers of the programming language C get to specify standards for runtime libraries, and operating manufacturers must implement those standards in the runtime libraries they provide for C?

Or do the operating system manufacturers tell the makers of C "here are my system calls to access the kernel, and you, the makers of C, have to write a runtime library using these system calls"?

Say I wanted to write my own high-level programming language for an x86 architecture. I create my preprocessor, compiler, and linker, and I assume that operating system manufacturers won't write the runtime libraries for me like they do for C. Therefore I am stuck writing runtime libraries using system calls that were optimized for use with C?
 
Technology news on Phys.org
  • #2
There are specs for runtime libraries, e.g., POSIX, that make an attempt to match the "impedance" between application programs and operating system internals. Given that C-like languages are so prevalent it behooves OS builders to support the spec in one way or another. Of course there are always special cases and features that need their own interfaces.

Most "real" OS's have some kind of separation of church and state between the kernel and the user, and this is usually what gets translated by the system libraries. Since C code can be very "close to the machine" it doesn't really add much overhead. It's really more of a convenience than a matter of optimization for the language.

On top of the syslibs are a bunch of application libs that provide user oriented features like GUI's and buffered file I/O. If you have to write your program over-and-over for each OS you will soon come to appreciate these standard libraries too.

The Java Virtual Machine is written in C or C++ and provides, IMHO rather klunky, access to lowlevel C functions via JNI. It makes use of all the "C" system and application libraries to ease the job of porting between machines. It's still not all that easy to port because of things like different ideas of signal handling and system management, but it's do-able.

I would expect that your new-improved-language would probably have a C-like nugget at the bottom on which you can bootstrap your own syntax. Or else you can study up on syslib implementation for each OS in which you are interested...
 
  • #3
I'm nowhere near knowledgeable enough to write my own language! I formulated a hypothetical to try to better understand the relationship between OSs and libraries more.

When you declare a variable in C, doesn't that require a system library, since the OS needs to make the space for that variable?

So if I have the definition:

int x=1;

is stdio.h the runtime library that declares int? And inside the actual stdio code, are there calls to system functions?

I understand things like a "for loop" can be translated directly into machine code without problem by a compiler. But variable declarations require system calls, and if you are working with C, that is fortunate because the system libraries are usually given in C by the OS manufacturer, but I'm unsure of what library in C allows you to declare variables.
 
  • #4
When you declare a variable in C, doesn't that require a system library, since the OS needs to make the space for that variable?

No. You use syscalls to allocate some initial amount of memory, and then do with that memory as you please. It would be extremely slow to have to travel into the kernel for every variable. Syscalls are needed to let your program communicate with the "outside world", for tasks like input/output or allocation/deallocation of additional memory. They are very general and not optimized for C.
 
  • #5
hamster143 said:
No. You use syscalls to allocate some initial amount of memory, and then do with that memory as you please. It would be extremely slow to have to travel into the kernel for every variable. Syscalls are needed to let your program communicate with the "outside world", for tasks like input/output or allocation/deallocation of additional memory. They are very general and not optimized for C.

I was looking at unistd.h , which seems to be a runtime system call library for C, written by unix manufacturers and not the makers of C compilers. Even if you allocate all the memory at once (as you say you make just one system call to allocate the memory), don't you still need a C header like unistd.h for that one system call? I was thinking that maybe stdio.h included unistd.h, but I'm not sure.
 
  • #6
It's not a system call library, it's just a header that declares available system calls and provides your program with ways to execute them. The library itself is probably called libc.a.
 
  • #7
hamster143 said:
It's not a system call library, it's just a header that declares available system calls and provides your program with ways to execute them. The library itself is probably called libc.a.

So somewhere in libc.a is a definition of the standard data types like int and double?

Because in the programming snippets for beginners that I've seen, it seems like they don't have to #include libc.a. , and the linker doesn't complain when they have:

int x=1;

All they include is stdio.h, so I thought maybe stdio.h includes declarations for int and double.

int x=1; looks like a system call function to create one byte of memory, and double y=100000; a system call to create two bytes of memory. One would think that maybe it'd look like this:

void int('argument')
{
create_memory_with_os(1 byte, int_store(argument));
}

void double('argument')
{
create_memory_with_os(2 bytes, double_store(argument));
}

But you say that a whole chunk of memory gets assigned, so it's not a one-by-one thing like this.

Are there any resources you could recommend to understand everything that's going on underneath the hood for a simple program, rather than how to write complex programs?
 
Last edited:
  • #8
Usually the basic libs, say libc.a, are included in your link automagically so you may not see an explicit reference in the commands to build an executable... or you might see something cryptic like "-lc"... To get to the functions in that library the C compiler may require you to include a header file which declares their signatures -- name, arguments, and return value.

Memory types like int and double are part of the language not the machine. A particular piece of hardware may have instructions to manipulate 1,2,4,and 8 byte quantities and interpret them as signed or un-signed collections of bits, as well as dealing with 4 or 8 byte lumps as floating-point values. But the language and it's compiler decide to call them ints and doubles and know how to allocate memory for them and use them appropriately. The fact that C's ints and doubles usually look identical to the hardware's registers and FP values derives from C being a very low level language. Java's Integer class is arithmetically identical to C's int, but way more complicated in it's implementation.

The point about memory allocation is that the program asks the system for a page of memory -- that's a syscall -- and then uses some local library functions to divide -- or allocate -- that memory into lumps that it can use. There are really three ways to do this in a C program, and all of them reflect common aspects of the hardware. You can do:

1. int x; outside of a function definition. This makes the compiler set aside 4 or so bytes in a "global" memory area that is allocated when the program is first loaded into memory.

2. int y; _inside_ a function definition. This makes the compiler set aside bytes on the program stack, which has been allocated at load time and changes size as needed.

3. your create_memory_with_os(2 bytes, double_store(argument)); which looks like a fancy way to say C's malloc() (actually malloc() is user level but I forget the syscall that gets new pages, so let's just pretend this is that...). This calls into the internals and returns a chunk of memory for the program to use that is neither in the pre-initialized area nor the stack.

Also hidden in the seemy underside of your program is some statup code that does all the stack and program area allocations, initializes everything, and then calls main(). That gets included in every link without much ado as well, although there is probably a way to override it.

I'm not sure where to send you to get more under-the-covers information. I tried googling "C language internals" and "C language startup" but didn't have the patience to dig very deep. This page has a bit of description of memory layout and how a program gets executed, but it's part of an embedded programming tutorial so it might be not the focus you want: http://www.bravegnu.org/gnu-eprog/c-startup.html But I'm sure that following some of those other links will cause you to stumble on the right thing.
 

1. What is the purpose of a runtime library in C language?

A runtime library is a collection of pre-written code that is used to provide necessary functions and utilities for a program to run properly. In C language, the runtime library is responsible for handling tasks such as memory management, input/output operations, and error handling.

2. What are some common functions included in the C runtime library?

Some common functions included in the C runtime library are malloc() for dynamic memory allocation, printf() for printing output, scanf() for taking user input, fopen() for file operations, and exit() for terminating a program.

3. How do runtime library standards affect compatibility across different operating systems?

Runtime library standards, such as the C Standard Library, provide a set of guidelines and specifications for how functions should behave. This helps ensure that programs written with the standard library will function properly on different operating systems, as long as they are compliant with the standard. However, some functions may have different implementations on different operating systems, which can lead to compatibility issues.

4. What is the role of an operating system in C language programming?

An operating system provides a platform for programs to run on by managing hardware resources and providing a set of services and functions for program execution. In C language programming, the operating system is responsible for loading and executing programs, managing memory, and handling input/output operations.

5. How can I ensure that my C program is compatible with different operating systems?

To ensure compatibility with different operating systems, it is important to follow the guidelines and standards set by the C Standard Library. It is also helpful to test the program on different operating systems and make any necessary adjustments. Additionally, using compiler flags and conditional compilation can help to address any differences in functions across operating systems.

Similar threads

  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
7
Views
466
Replies
6
Views
1K
  • Programming and Computer Science
2
Replies
59
Views
7K
  • Programming and Computer Science
4
Replies
107
Views
5K
  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
Replies
8
Views
1K
Back
Top