Before you access any ports, you must give your program permission to do so by calling the ioperm() function (declared in unistd.h) before any I/O port accesses. The syntax is ioperm(from, num, turn_on), where from is the first port number to give access to, and num the number of consecutive ports to give access to. The last argument is a Boolean value specifying whether to give access to the program to the ports (true (1)) or to remove access (false (0)). ioperm() can only give access to ports 0x000 through 0x3ff; for higher ports, you need to use iopl() (which gives you access to all ports at once).
Accessing the ports
To input a byte (8 bits) from a port, call inb(port), it returns the byte it got. To output a byte, call outb(value, port) (please note the order of the parameters).
wait for more ;)
Device drivers are mainly categorized in four different categories namely character drivers, block drivers, terminal drivers and streams. Character drivers transmit information from the user to the device (or vice versa) byte per byte. The following figure will make it easy to understand this class of drivers:
The file_operations Structure
The file_operations structure is defined in linux/fs.h, and holds pointers to functions defined by the driver that perform various operations on the device. Each field of the structure corresponds to the address of some function defined by the driver to handle a requested operation.
The file structure
Each device is represented in the kernel by a file structure, which is defined in linux/fs.h. It's not the same thing as a FILE, which is defined by glibc and would never appear in a kernel space function. It represents an abstract open `file' which is represented by a structure named inode.
Registering A Device
Adding a driver to your system means registering it with the kernel. This is synonymous with assigning it a major number during the module's initialization. You do this by using the register_chrdev function, defined by linux/fs.h.
where unsigned int major is the major number you want to request, const char *name is the name of the device as it'll appear in /proc/devices and struct file_operations *fops is a pointer to the file_operations table for your driver. A negative return value means the registration failed. If you pass a major number of 0 to register_chrdev, the return value will be the dynamically allocated major number. The downside is that you can't make a device file in advance, since you don't know what the major number will be.
Unregistering A Device
We can't allow the kernel module to be rmmod'ed whenever root feels like it. If the device file is opened by a process and then we remove the kernel module, using the file would cause a call to the memory location where the appropriate function (read/write) used to be. If we're lucky, no other code was loaded there, and we'll get an ugly error message. If we're unlucky, another kernel module was loaded into the same location, which means a jump into the middle of another function within the kernel. The results of this would be impossible to predict, but they can't be very positive.
Accessing Device Files
Device files are supposed to represent physical devices. Most physical devices are used for output as well as input, so there has to be some mechanism for device drivers in the kernel to get the output to send to the device from processes. This is done by opening the device file for output and writing to it, just like writing to a file.
In many cases drivers compiled for similar kernel versions will work. Pre-compiled modules in the form of RPMS for popular distributions are frequently available. If a pre-compiled module is not available; you'll have to compile one from the driver source code, or the source code RPM (SRPM).
* Verify that the source code for your current kernel version is installed.
* If you don't have a /usr/include/linux/version.h file, do cd /usr/src/linux; make include/linux/version.h
* Copy the driver source code to a source directory
* Compile the file using the compile-command at the bottom of the driver source file. If a compile-command is not there use the following compile command:
gcc -DMODULE -D__KERNEL__ -O6 -c driver.c
* As 'root', test the module by doing "insmod driver.o".
* Install the driver module in the proper location for your distribution. This is usually /lib/modules/kernel-version/net/driver.o. The command to do this is
install -m 644 driver.o /lib/modules/`uname -r`/net/
Testing the New Module
As 'root', load the module using "insmod driver.o" and execute the appropriate 'route add -net ...' for your local network.
If the networking works correctly, add the module to your system configuration. For Slackware and most other systems, add the insmod command to /etc/rc.d/rc.inet1 or /etc/rc.d/rc.local. RedHat users should add the insmod line to /etc/rc.d/rc.modules or copy driver.o to /lib/modules/`uname -r`/net/ and add the following line to /etc/conf.modules:
alias eth0 driver
Consider the following command "/sbin/insmod driver.o full_duplex=1,0,1". This command sets the full_duplex flag for the first and third cards of this type.
To set module parameters when the module is loaded automatically, add the following line to /etc/conf.modules
alias eth0 driver
options driver full_duplex=1,0,1 debug=0
....to be contd. ;)
My memory with Novell goes back to the time when I first installed SuSE 9(Enterprise Desktop) on my Desktop with minimal requirements. Now I work on my Lenovo 3000 N100 laptop. I have tried several flavors of linux on my notebook but none satisfied my needs so far. I began with Red Hat 9. It was sort of old so I shifted to Fedora Project. I installed Fedora core 4 but again my sound card and the network card was creating dubious issues. After fedora I switched to Mandrake. Mandrake 10.1 was enticing with a nice KDE and GNOME env, but again, it didn't recognize my Wireless card Intel Pro 802.11 a/b/g. I switched to RHEL4 (Red Hat Enterprise Linux) in a hope that this enterprise version be something different and would satisfy my needs, rather it added to my disappointment...This time my touch pad (Synaptics) was creating problems. [ As soon as I place my finger on the touch pad, it sort of traveled the whole screen randomly even when my finger was static on the touchpad]. I completely lost hopes after this.
A week ago one of my Linux enthusiast friend gave me a downloaded copy of OpenSuSE 10.3. Voila! it worked. Yes, finally I found a complete system for my machine. I installed the same copy on my desktop (PIII 1.13 GHz with 384 M RAM). Bravo!! no issues with memory management. With KDE 4 and Yast2, this OS can handle anything you want. Hardware probing is not a problem either, no issues with Wireless card, Network card or the touchpad. The website of OpenSuSE offers any user to search for the software repositories and '1-click install' feature. Extensive online and offline documentation is also available for those who are new to Linux or shifting from Windows to Linux. Apart from this, an integrated Virtualization software to try other Operating systems is also included in OpenSuSE 10.3. I would recommend OpenSuSE to OS enthusiasts right away. Seriously, I was quite troubled with linux installations on my laptop as my projects require kernel dev. Now with this OS, all's well and running ;)
Wait till next post when I write more about this legendary OS I am in love with!
1) In first way, the process is put in the crontab file which wakes up the module by a system call, for example by accessing a file or writing to a file. I personally don't refer this mode, however -- we run a new process off of crontab, read a new executable to memory, and all this just to wake up a kernel module which is in memory anyway.
2) The other way would be to create a function that which can be called once for every interrupt. The way we can do this is by creating a task initially held in a struct tq_struct, which holds a pointer to the function. Then, we can use queue_task to put that task on a 'task list' called tq_timer, which is the list of tasks that are to be executed on the next interrupt. Because we want the function to keep on being executed, we need to put it back on tq_timer whenever it is called, for the next timer interrupt.
Another thing to be kept in mind is this: When we remove a module by the command rmmod, its reference count is checked first. If it is zero, module_cleanup is called. Next, the module is removed from memory with all its functions. Nobody checks to see if the timer's task list happens to contain a pointer to one of those functions, which will no longer be available. Ages later (from the computer's perspective, from a human perspective it's nothing, less than a hundredth of a second), the kernel has a timer interrupt and tries to call the function on the task list. Unfortunately, the function is no longer there. In most cases, the memory page where it sat is unused, and you get an ugly error message. But if some other code is now sitting at the same memory location, things could get very ugly. Unfortunately, we don't have an easy way to unregister a task from a task list.
Since cleanup_module can't return with an error code (it's a void function), the solution is to not let it return at all. Instead, it calls sleep_on or module_sleep_on to put the rmmod process to sleep. Before that, it informs the function called on the timer interrupt to stop attaching itself by setting a global variable. Then, on the next timer interrupt, the rmmod process will be woken up, when our function is no longer in the queue and it's safe to remove the module. ;)
thanks. wait for more
A thread is a point of control flow in a task. A task
exists to provide resources for the threads it contains. This split is made to provide
for parallelism and resource sharing.
- is a point of control flow in a task.
- has access to all of the elements of the containing task.
- executes (potentially) in parallel with other threads, even threads within the same task.
- has minimal state information for low overhead.
- is a collection of system resources. These resources, with the exception of the address space, are referenced by ports. These resources may be shared with other tasks if rights to the ports are so distributed.
- provides a large, potentially sparse address space, referenced by virtual address.Portions of this space may be shared through inheritance or external memory management.
- contains some number of threads.
said that “task Y does X,” what is really meant is that “a thread contained within
task Y does X.” ;)
I agreed as I couldn't talk myself out of that. The topic list included several enticing topics but the one that fascinated me the most was VoIP.
here's a glimpse of the abstract I prepared....
VoIP (Voice over Internet Protocol)
Author: - Jasjeet Chawla
Student, I.E.T. BHADDAL
Voice over Internet Protocol (VoIP) allows you to make telephone calls using an Internet connection instead of a regular telephone line. One of the most important things to point out is that VoIP is not limited to voice communication. In fact, a number of efforts have been made to change this popular marketing term to better reflect the fact that VoIP means voice, video, and data conferencing. VoIP is important because, there is an opportunity to bring about significant change in the way that people communicate. It allows the usage of a single high-speed Internet connection for all voice, video, and data communications, usually termed as convergence. Virtually every device in the world uses a standard called Real Time Protocol(RTP) for transmitting audio and video packets between communicating computers. Before audio or video media can flow between two computers, various protocols must be employed to find the remote device and to negotiate the means by which media will flow between the two devices. The protocols that are central to this process are commonly referred to as call-signaling protocols, the most popular of which are H.323 and Session Initiation Protocol (SIP) and they both rely on static provisioning. Fundamentally, H.323 and SIP allow users to do the same thing: to establish multimedia communication (audio, video, or other data communication), however, they differ significantly in their design.
In this paper, I intend to present my case studies on two key VoIP enabled software applications viz. SKYPE and X-LITE: Skype is a "complete black box" -- that is, it is extremely hard for the lay user to identify what it is doing, or what it might be doing, or how appropriately it is doing it. Skype has been criticized over its use of a proprietary protocol, instead of an open standard like H.323, IAX, or SIP, since this makes it impossible for other providers to interact with the Skype network. X-Lite provides endpoint VoIP solutions that use internet-based telephony servers within an enterprise LAN (Local Area Network) or VoIP service provider network.
I personally feel that kernel programming is the next step after you have strong concepts in C programming. 'We must believe in order to acheive.' Yeah that should be the driving phrase if you want to dedicated yourself to kernel programming and OpenSource developer community!
I could have written a lot on Kernel Programming and starting off with device drivers. But due to scarcity of time I have to wind up quickly today on a note that I'll be back with more.
Meanwhile, you all kernelHEADS can go through this article which provides with the basics of Writing Device Drivers.
Sorry for the small post. I'll surely be back with more. Take care. Ciao!
In the case of Linux, the following steps are performed to boot the kernel:
1) The boot loader program (e.g. lilo or grub) starts by loading the vmlinuz from disk into memory, then starts the code executing.
2) After the kernel image is decompressed, the actual kernel is started. This part of the code was produced from assembler source; it is totally machine specific. Technically at this point the kernel is running. This is the first process (0) and is called swapper. Swapper does some low level checks on the processor, memory and FPU availability, then places the system into protected mode. Paging is enabled.
3) Interrupts are disabled (every one) though the interrupt table is set up for later use. The entire kernel is realigned in memory (post paging) and some of the basic memory management structures are created.
4) At this point, a function called start_kernel is called. start_kernel is physically located in /usr/src/linux-2.4.18-27.7.x/init/main.c and is really the core kernel function - really the equivalent of the void main(void). main.c itself is virtually the root file for all other source and header files.
5) start_kernel sets up the memory, interrupts and scheduling. In effect, the kernel has now has multi-tasking enabled. The console already has had several messages displayed to it.
6) The kernel command line options are parsed (those passed in by the boot loader) and all embedded device driver modules are initialized.
7) Further memory initializations occur, socket/networking is started and further bug checks are performed.
8) The final action performed by swapper is the first process creation with fork whereby the init program is launched. Swapper now enters an infinite idle loop.
It is interesting to note that as a linear program, the kernel has finished running! The timer interrupts are now set so that the scheduler can step in and pre-empt the running process. However, sections of the kernel will be periodically executed by other processes.
This is the boot sequence from a kernel point of view. For a more comprehensive Boot Sequence explanation... you can view my friend's blog HERE.
Lets get straight to the point why I created this blog for. I am not your teacher to take you through the basics of Kernel/C programming under linux. ;) and I consider that people reading my blog have a prior knowledge of programming in C. (sorry if this is a jump from beginner's level to Novice...This post is for people who want to stop reading and start coding straightaway. Although I will touch on how things are done in the kernel in several places, that is not my purpose. There are enough good sources which do a better job than I could have done!)
A kernel module is not an independent executable, but an object file which will be linked into the kernel in runtime. As a result, they should be compiled with the -c flag. Also, all kernel modules have to be compiled with certain symbols defined.
- __KERNEL__ -- This tells the header files that this code will be run in kernel mode, not as part of a user process.
- MODULE -- This tells the header files to give the appropriate definitions for a kernel module.
- LINUX -- Technically speaking, this is not necessary. However, if you ever want to write a serious kernel module which will compile on more than one operating system, you'll be happy you did. This will allow you to do conditional compilation on the parts which are OS dependent.
There are other symbols which have to be included, or not, depending on the flags the kernel was compiled with. If you're not sure how the kernel was compiled, look it up in /usr/include/linux/config.h
- __SMP__ -- Symmetrical MultiProcessing. This has to be defined if the kernel was compiled to support symmetrical multiprocessing (even if it's running just on one CPU). If you use Symmetrical MultiProcessing, there are other things you need to do...lets say Interrupt handling. ;)
- CONFIG_MODVERSIONS -- If CONFIG_MODVERSIONS was enabled, you need to have it defined when compiling the kernel module and and to include /usr/include/linux/modversions.h. This can also be done by the code itself.
# Makefile for a basic kernel module
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX
hello.o: hello.c /usr/include/linux/version.h
$(CC) $(MODCFLAGS) -c hello.c
echo insmod hello.o to turn it on
echo rmmod hello to turn if off
echo X and kernel programming do not mix.
echo Do the insmod and rmmod from outside X.
So, now the only thing left is to su to root , and then insmod
hello and rmmod hello to your heart's content.
While you do it, notice your new kernel module in /proc/modules.
oops...seems much for the day...lol...never mind ...
i will be back with more! tc all. keep reading. Adios!
To me, a simple definition would do : Kernel is the core or the crux of the operating system! It is the only link between the hardware and the software. Seems simple to understand, no?? Well....look at this diagram of the Linux kernel, and you'll be able to adjudicate for yourself. ;)
Diagram of the linux kernel. (click to view and enlarge)
The kernel's primary purpose is to manage the computer's resources and allow other programs to run and use these resources, these resources include the CPU, the main Memory (RAM), and the I/O devices.
Typically, the kernel is responsible for memory management, process & task management and disk management. These concepts are the base for a Kernel development (KernelDev) which I shan't explain here.
Furthermore, the aforesaid tasks are done differently by different kernels, depending on their design and implementation.
My projects have been keeping me on my toes so i feel this brief introduction to OS Kernel will fill you up for the day. Although, more can be read online. Wikipedia is the best online documentation for everything. Wait till my next post. Adieu~!
My special thanks to several people who have inspired me to write either by direct word of mouth or by their successful blogs/sites : Puneet Chawla, Nitin , Ankur .
I have been working on the linux kernel for about an year now. Written couple of device drivers and tweaked plenty of modules in MINIX OS.
Will write more about everything related to the mysterious OS and its Kernel in the upcoming posts.
Have a great day ;)