Kernel in C
Kernel in C
Hi,
If I want to create my kernel in C do I need to have some kind of memory manager in place? Also, is it possible to create global variables in C without a memory manager?
If I want to create my kernel in C do I need to have some kind of memory manager in place? Also, is it possible to create global variables in C without a memory manager?
Re:Kernel in C
a lot of memory is empty at boot...
so you can just load your C kernel into 0x1000 (or somewere else)
yes, you can use global variables but you can't give them a value
:/
(gcc adds a lot of add al,[eax] or something (used disassembly)
don't know why it does...)
so you can just load your C kernel into 0x1000 (or somewere else)
yes, you can use global variables but you can't give them a value
:/
(gcc adds a lot of add al,[eax] or something (used disassembly)
don't know why it does...)
Re:Kernel in C
I think I know what your talking about, tell me if i'm wrong....
like if you use "int someint = 20;"
it makes my C kernel huge.
but when you use
"int someint;
void somevoid()
{
someint = 20;
}"
it doesn't do that,
right?
like if you use "int someint = 20;"
it makes my C kernel huge.
but when you use
"int someint;
void somevoid()
{
someint = 20;
}"
it doesn't do that,
right?
Re:Kernel in C
The difference between:
a)
int somevar = 20;
int main(void)
{
return 0;
}
and b)
int main(void)
{
int somevar = 20;
return 0;
}
is that in (a), somevar is put into the .data section of the kernel image and exists on disk, which is how it gets its value at load time. In (b), somevar exists on the stack in the main() function, and isn't created until main() is called.
The reason that your image goes huge when you declare one global variable is that the linker pads each section to 4096 bytes (it does that to .text, the code, too). If you add another global variable, you'll see that the image doesn't grow in size, and it won't grow until you've added enough variables to move onto the next 4096-byte page.
If you do this:
int somevar;
int main(void)
{
somevar = 20;
return 0;
}
...then you won't see any increase in the size of the kernel file on disk, because the linker doesn't need to save the default value of somevar on disk, because it doesn't have one. In this case, somevar goes into the .bss section, and the loader is expected to zero that section at load time.
a)
int somevar = 20;
int main(void)
{
return 0;
}
and b)
int main(void)
{
int somevar = 20;
return 0;
}
is that in (a), somevar is put into the .data section of the kernel image and exists on disk, which is how it gets its value at load time. In (b), somevar exists on the stack in the main() function, and isn't created until main() is called.
The reason that your image goes huge when you declare one global variable is that the linker pads each section to 4096 bytes (it does that to .text, the code, too). If you add another global variable, you'll see that the image doesn't grow in size, and it won't grow until you've added enough variables to move onto the next 4096-byte page.
If you do this:
int somevar;
int main(void)
{
somevar = 20;
return 0;
}
...then you won't see any increase in the size of the kernel file on disk, because the linker doesn't need to save the default value of somevar on disk, because it doesn't have one. In this case, somevar goes into the .bss section, and the loader is expected to zero that section at load time.
Re:Kernel in C
So will be both of these examples be available globally to my kernel, and retain the same value? (ie outside of the main() function)Tim Robinson wrote:The difference between:
a)
int somevar = 20;
int main(void)
{
return 0;
}
and b)
int main(void)
{
int somevar = 20;
return 0;
}
is that in (a), somevar is put into the .data section of the kernel image and exists on disk, which is how it gets its value at load time. In (b), somevar exists on the stack in the main() function, and isn't created until main() is called.
Since my kernel will not be loaded like a normal application, will I have to zero this section in my boot code before jumping to it?Tim Robinson wrote:In this case, somevar goes into the .bss section, and the loader is expected to zero that section at load time.
Also, I am not that knowledgable in C, how do I export/import variables and functions from a source file?
Re:Kernel in C
Clearly the somevar inside main() won't be accessible outside main(). Global variables will though.PlayOS wrote:So will be both of these examples be available globally to my kernel, and retain the same value? (ie outside of the main() function)
Yes (although if you are using GRUB, it will do that for you).Since my kernel will not be loaded like a normal application, will I have to zero this section in my boot code before jumping to it?
To export a function or variable, don't make it static. In other words, all functions and variables without the 'static' keyword are exported.Also, I am not that knowledgable in C, how do I export/import variables and functions from a source file?
To import a function, declare the function at the top of your source file or (better) in a header file.
To import a variable, declare the function with the extern keyword.
e.g.:
Code: Select all
---- file1.c
int var1; // Accessible anywhere
static private_var; // Accessible only inside file1.c
// Accessible anywhere
void function1(void)
{
printf("Hello, world %d\n", var1);
}
// Accessible only inside file1.c
static void private_function(void)
{
}
---- file2.c
void function1(void);
extern int var1;
int main(void)
{
var1 = 42;
function1();
return 0;
}
Re:Kernel in C
Ah, I see, I had it in my mind that example b, was
int somevar;
int main(void)
{
somevar = 20;
return 0;
}
would this still cause a 4KB data space to be created? or would this assign this value at runtime? Would somevar retain the same value after main() exits?
int somevar;
int main(void)
{
somevar = 20;
return 0;
}
would this still cause a 4KB data space to be created? or would this assign this value at runtime? Would somevar retain the same value after main() exits?
Re:Kernel in C
It will cause a 4KB bss space to be created in memory, but not on disk.PlayOS wrote: Ah, I see, I had it in my mind that example b, was
int somevar;
int main(void)
{
somevar = 20;
return 0;
}
would this still cause a 4KB data space to be created?
No, because the linker know that uninitialised global variables will be zeroed by the loader.or would this assign this value at runtime?
Yes, because it's global.Would somevar retain the same value after main() exits?
Re:Kernel in C
Thanks this is all good help. Also, what happens with constants? What would happen in this case:
#define CONSTANT 100
int main( void )
{
int x = CONSTANT;
return 0;
}
#define CONSTANT 100
int main( void )
{
int x = CONSTANT;
return 0;
}
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Kernel in C
a #define applies at preprocessing time. there is no difference in the code generated between
and
Code: Select all
#define A_DEFINED_CONSTANT 123456
int x = A_DEFINED_CONSTANT
Code: Select all
int x = 123456
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Kernel in C
by the by, your 4Kb problem is due to the fact that by default, ELF files do some padding to speed up file mapping in paged environment. I think there is an option to change the section mapping to - say - 16 bytes, or even just one byte. There is also a way (using complex .ld files to make the image on disk have no padding while the memory-mapped image will have some.
unfortunately, i have focused on COFF files, so i don't know the options for ld, but i know this should be feasible...
unfortunately, i have focused on COFF files, so i don't know the options for ld, but i know this should be feasible...
Re:Kernel in C
So then all preprocessors have no affect on the disk image.
Ok, maybe I will look into the ELF format if I come to really need this, thanks.
Ok, maybe I will look into the ELF format if I come to really need this, thanks.
Re:Kernel in C
Not directly. With the exception of the #pragma directives, which send options to the compiler, all preprocessor directives act on the source code before it is compiled; they are strictly textual replacements.PlayOS wrote: So then all preprocessors have no affect on the disk image.
For a few examples:
A defined name's value is inserted directly into the source code, without regard to it's meaning. Thus,
Code: Select all
#define MYCONST 1234
x = MYCONST;
Code: Select all
x = 1234;
after preprocessing; this is the code actually seen by the compiler itself. Thus one could write
Code: Select all
int x = 3;
int y;
#define DOUBLEX x*x
y = DOUBLEX;
Code: Select all
int x = 3;
int y;
y = x * x;
Code: Select all
#define SQUARE(x) x *x
int x, y, z;
char a, b;
y = z = 2;
x = SQUARE(y);
y = SQUARE(y + z);
z = SQUARE(x + y * z);
a = 'a';
b = SQUARE(a);
will result in the following code going to the compiler:
Code: Select all
int x, y, z;
char a, b;
y = z = 2;
x = y * y;
y = y + z * y + z;
z = x + y * z * x + y * z;
a = 'a';
b = a * a;
Code: Select all
#define BIGMACRO(x, y, z) if (x > z) /
{ /
x = pow(y, 4); /
y = 5; /
} /
else /
{ /
z = y * x; /
y = (int) time(NULL); /
}
Includes add text from other files to the current file.
Code: Select all
#include <stdio.h>
inserts the contents of the file stdio.h into your source code.
Conversely, preprocessor switches control which text should be excluded from the source code.
Code: Select all
srand((int) time(NULL)); /* use current time for random seed */
y = rand();
#ifdef ___SOLARIS___
x += y;
#elif defined ___LINUX___
x += y > 0 ? y : 1;
#elif defined ___WINDOWS___
if (phase_of_moon() != "GIBBOUS" && ulBills_bankroll > MAXULONG)
x += y * (x -y);
#endif
z = factorial(x);
Code: Select all
srand((int) time(NULL)); /* use current time for random seed */
y = rand();
x += y > 0 ? y : 1;
z = factorial(x);
It should be noted thast most of what has been said about the CPP applies, generally speaking, to assembler macros as well - indeed, in the case of as or gas, the assembly macro processor often is the C preprocessor, though the m4 preprocessor is also often used. While other macro systems (such as MASM's opr NASM's) are more closely tied to the assembler itself, the basic function of all of them is to alter the text of the source code before the actual compiling or assembling takes place.