Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Wednesday, January 30, 2013

Dual Boot Incorrect Clock


Windows / Linux dual boot incorrect system time problem

I always encounter this problem after new installation of Windows / Linux on my PC. If I switch between OSs, Windows shows GMT time instead of local time, although when I check settings, it shows me that local time setting is still OK, for example, I can still see GMT+6 is selected, but the time is wrong. I keep forgetting the fix, so I will be noting it down here for future fix.

After a little bit Google-ing, I found the reason behind this is, Linux or BSD based OSs set BIOS time to UTC / GMT, while Windows sets the clock to local time. So to fix this, either we need to tell Windows to store universal time, or tell Linux to store local time. However, seems like doing this on Windows is easier using "regedit". we will need to add a flag "RealTimeIsUniversal" so that Windows acts accordingly. There is a similar flag which can be used in Linux as well.

For windows fix: go to start menu and write "regedit" (without quotes) on the search box, and hit enter. The regedit.exe will start. Now from left side, navigate to

HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Control -> TimeZoneInformation
Now right click on an empty spot on the right side panel and select
New -> DWORD (32bit) Value
Give the name "RealTimeIsUniversal" (without quotes), double click on it, and give the value 1, done! Next time you start Windows after using Linux, the time setting should be fine, at least working fine for me. Also, I've picked this solution instead of changing Linux flags, because, I feel like all clocks should be set to UTC time, so that it creates no problem when using internet.

Monday, July 25, 2011

Character Device Driver


Linux Kernel Programming: Writing a simple character device driver

Probably the simplest example for a simple linux device driver is a character device driver using virtual buffer, i.e. without using any real device, a block of memory will be used to simulate the properties of a buffer. We will be dealing only with the major device number, minor device number is used internally by the driver, but will be skipped in this example for simplicity. Also, the major number will be statically declared. I call this device "chardev", however, you can put any name you like. Like any other kernel driver modules, it has 6 basic functionalities, among which, two are module_init and module_exit functions, namely, device_init and device_exit. The rest four functions are from file_operations structures, read, write, open and release which are accomplished by device_read, device_write, device_open and device_release functions here. Actions of each functions are quite simple, device_init registers the device when the module is loaded and device_exit unregisters it upon removal. device_open tracks whether the device is already open or not, and device_release may be used to free any used space, however, we are allocating memory statically, so nothing much to do here. And finally, device_write is used to write a string to the device buffer which is in kernel space from an address which is in user space, for example, when we use `echo "hi" > /dev/chardev`, string "hi" (without quotes) will be written to device buffer. device_read is the opposite of device_write function. It is used when user space calls the device to read something from the buffer, for example `cat /dev/chardev`. Basically what it does is, just exports buffer data to a user space address. More details of each operation and functions used here in the text books or from online resources. Now here is a simple implementation. Don't expect it to be too smart anyway.
 /* AUTHOR: Zobayer Hasan PROGRAM: Character Device Driver DATE: Monday, 25 July 2011 VERSION: 1.0 */  #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/fs.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/types.h> #include <linux/errno.h> #include <asm/system.h> #include <asm/uaccess.h>  #define DEVICE_NAME "chardev" #define BUFFER_SIZE 1024  MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Zobayer Hasan"); MODULE_DESCRIPTION("A simple character device driver."); MODULE_SUPPORTED_DEVICE(DEVICE_NAME);  int device_init(void); void device_exit(void); static int device_open(struct inode *, struct file *); static int device_release(struct inode *, struct file *); static ssize_t device_read(struct file *, char *, size_t, loff_t *); static ssize_t device_write(struct file *, const char *, size_t, loff_t *);  module_init(device_init); module_exit(device_exit);  static struct file_operations fops = {     .read = device_read,     .write = device_write,     .open = device_open,     .release = device_release };  static int device_major = 60; static int device_opend = 0; static char device_buffer[BUFFER_SIZE]; static char *buff_rptr; static char *buff_wptr;  module_param(device_major, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); MODULE_PARM_DESC(device_major, DEVICE_NAME " major number");  int device_init() {     int ret;     ret = register_chrdev(device_major, DEVICE_NAME, &fops);     if(ret < 0) {         printk(KERN_ALERT "chardev: cannot obtain major number %d.\n", device_major);         return ret;     }     memset(device_buffer, 0, BUFFER_SIZE);     printk(KERN_INFO "chardev: chrdev loaded.\n");     return 0; }  void device_exit() {     unregister_chrdev(device_major, DEVICE_NAME);     printk(KERN_INFO "chardev: chrdev unloaded.\n"); }  static int device_open(struct inode *nd, struct file *fp) {     if(device_opend) return -EBUSY;     device_opend++;     buff_rptr = buff_wptr = device_buffer;     try_module_get(THIS_MODULE);     return 0; }  static int device_release(struct inode *nd, struct file *fp) {     if(device_opend) device_opend--;     module_put(THIS_MODULE);     return 0; }  static ssize_t device_read(struct file *fp, char *buff, size_t length, loff_t *offset) {     int bytes_read = strlen(buff_rptr);     if(bytes_read > length) bytes_read = length;     copy_to_user(buff, buff_rptr, bytes_read);     buff_rptr += bytes_read;     return bytes_read; }  static ssize_t device_write(struct file *fp, const char *buff, size_t length, loff_t *offset) {     int bytes_written = BUFFER_SIZE - (buff_wptr - device_buffer);     if(bytes_written > length) bytes_written = length;     copy_from_user(buff_wptr, buff, bytes_written);     buff_wptr += bytes_written;     return bytes_written; }  /* End of Source Code */ 
Ha, quite tiny code. obviously huge optimization and improvement await here. Now, we have assigned major number 60, before doing anything, make sure your system has not assigned 60 as a major number for any device. To check this, just use the command:
 $ ls -l /dev 
Just try to find out a number which is not already used as a major number (1st number) and assign it to the variable device_major, or you can do it through command line also when using insmod command to insert the module. To compile this program, just use the following Makefile (name the file Makefile):
 obj-m := chardev.o all:     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules clean:     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean 
Note, do not copy this, you must write it by typing to avoid problems, and spaces before keyword make must be tab character. And I assumed the source file name 'chardev.c'. I am using ubuntu platform, so you might need to change this a bit, however I think it will work just fine. To run the makefile, go to the directory it is in along with the sourcefile,
 $ sudo make 
If you don't get any errors, that means you have successfully compiled the source file to generate chardev.ko which is the kernel module. Now, you need to create a device with major number 60 or what you want to assign:
 $ sudo mknod /dev/chardev c 60 0 $ sudo chmod 666 /dev/chardev $ sudo insmod chardev.ko 
In mknod command, c defines that it will be a character device, then we give read+write permissions for everyone, so that the device can be usable. Then insmod command inserts chardev device in modules, you can see it in various ways, like, using `lsmod | grep chardev` or `ls -l /dev | grep chardev` or `modinfo chardev` or you can just use `dmesg` to display kernel log to see whether the loading printk printed anything (last line of the output of dmesg command). Now it's upto you to do some experiments, like to write to device, just redirect the output of any program with a output redirect operator `>` (be careful, buffer here is allocated only 1KB). And to read from the device, open it (/dev/chardev) with any program and read from it, like, just using `cat /dev/chardev`. Finally, when done with experimenting, you may wish to unload the driver and remove the device:
 $ sudo rmmod chardev $ sudo rm /dev/chardev 
That's pretty much of it. Good luck & have fun!

Friday, July 1, 2011

Beginning Kernel Programming


I have started to learn kernel programming shortly, well, this thing is not much interesting to me, mostly due to academic purpose.

I have been following The Linux Kernel Module Programming Guide which was suggested by our instructor. However, I've found that this one is already a bit old and I faced a lot of trouble even to see the simple yet extremely popular "hello world" on my kernel log. As I use ubuntu distribution (version 11.04), there are lot of differences inside and outside. So I have cooked the first code as followed (as in the guide, it is explained there.)

 #include <linux/module.h> #include <linux/kernel.h>  int init_module(void) {     printk(KERN_ALERT "Hello world 1.\n");     return 0; }  void cleanup_module(void) {     printk(KERN_ALERT "Goodbye cruel world 1.\n"); } 

However, this goes quite well without any trouble. But I have to change the "Makefile" a bit to successfully compile this Hello World code (tabs will be expanded as spaces here).

 obj-m += hello-1.o all:     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules clean:     make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean 

I'm lucky that I figured out only pwd is not working, I had to add shell instruction with it.

After this, everything went on quite well:

$ sudo make

This generated the following output with no errors:

 make -C /lib/modules/2.6.38-8-generic/build M=/home/zobayer/Lab/system/kernel modules make[1]: Entering directory `/usr/src/linux-headers-2.6.38-8-generic'   Building modules, stage 2.   MODPOST 1 modules make[1]: Leaving directory `/usr/src/linux-headers-2.6.38-8-generic' 

Now to install the module:

$ sudo insmod ./hello-1.ko

So I opened the file /proc/modules to check if I was successful and whoa, it was there...

The I removed it from modules:

$ sudo rmmod hello-1.ko

Now I had to make another change, when I try to open /var/log/messages as the guide suggest, I've found that there is no such file, instead, I had to open /var/log/kern.log, and at the far bottom, I've found what I had been looking for:

 ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...  ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...  Jul  1 14:17:38 zobayer kernel: [   48.569441]  Jul  1 14:17:38 zobayer kernel: [   48.569447] nouveau 0000:01:00.0: VGA-1: EDID block 0 invalid. Jul  1 14:17:38 zobayer kernel: [   48.569452] [drm] nouveau 0000:01:00.0: DDC responded, but no EDID for VGA-1 Jul  1 14:17:38 zobayer kernel: [   48.596016] [drm] nouveau 0000:01:00.0: Load detected on output A Jul  1 14:18:12 zobayer kernel: [   82.640352] Marking TSC unstable due to cpufreq changes Jul  1 14:18:12 zobayer kernel: [   82.640450] Switching to clocksource acpi_pm Jul  1 15:23:31 zobayer kernel: [ 4001.644627] hello_1: module license 'unspecified' taints kernel. Jul  1 15:23:31 zobayer kernel: [ 4001.644636] Disabling lock debugging due to kernel taint Jul  1 15:23:31 zobayer kernel: [ 4001.647429] Hello world 1. Jul  1 15:24:58 zobayer kernel: [ 4088.648118] Goodbye cruel world 1. 

I think I have to change many things in future, but so far, this may be a good start...

Edit: An addition by Surid vai:

Mellowhost Surid

/var/log/messages is the general log file and kern.log is the kernel log file. In redhat system, until explicitly defined, there is no kern.log, I believe that book is written based on redhat kernels, that is why they are using messages. B...ut for any system, the command "dmesg" should print those module outputs. dmesg is the kernel ring buffer log. You are using Ubuntu, this is why by default it is using kern.log

If you would like to change the kernel log file, you would need to use klogd. It is a daemon to catch and handle kernel messages. Now find how can you make the change :)

http://linux.die.net/man/8/klogd


Tuesday, May 17, 2011

Writing My Own Shell


Hello everyone, I am back after a huge pause, actually I was busy for nothing the past few months, and felt the necessity to write something here. So I am going to note down something I recently did. I just finished writing my own shell program for linux, which is simple, doesn't support piping or redirection, but most of the features are available, so, it actually looks like the common "sh" shell. I am not going to describe the big code, you have to understand what it is doing :p

The source code. Its free to use. I have written the whole code by myself and surely I am not an expert, so if anything happens to your computer, I don't know you :p

To compile, you can use this makefile in su mode (note tab character is important).

Some features, you can invoke single commands like this:

$ doit <command [arguments...]>

Also, you can start the shell by simply calling it without any argument:

$ doit

Then it will behave like a shell program and you can give commands one by one just like a simple shell. It implements its own "cd", "pwd" and "jobs" command (you should know what they mean). You can call background processes by appending & at the end of the command... and so on. You can display resource utilizations as well. Just dig through the code, I will enhance it more if I get time :)


Friday, December 10, 2010

getch() & getche() in gcc/g++


As sometimes, we use the header "conio.h" in windows (although deprecated), we feel the need for it sometimes in linux as well, and unfortunately, in linux, i.e. in gcc/g++, there is nothing built in like "conio.h", to be more precise, getch() and getche() functions. getch() reads directly from console, without any buffering, and so does getche(). The difference between them is, getch() doesn't echo the pressed key on the screen while getche() does.

Well, it's not very hard to write your own getch() and getche() routines in linux if you know some system programming, and console attributes used in linux. All you need to do, is to stop stdin buffering before reading the character, and then restore the old settings again. Here goes the simple "conio.h" for gcc/g++:

 /* AUTHOR: zobayer INSTRUCTION: just make this file a header like "conio.h" and use the getch() and getche() functions. */ #include <termios.h> #include <unistd.h> #include <stdio.h>  /* reads from keypress, doesn't echo */ int getch(void) {     struct termios oldattr, newattr;     int ch;     tcgetattr( STDIN_FILENO, &oldattr );     newattr = oldattr;     newattr.c_lflag &= ~( ICANON | ECHO );     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );     ch = getchar();     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );     return ch; }  /* reads from keypress, and echoes */ int getche(void) {     struct termios oldattr, newattr;     int ch;     tcgetattr( STDIN_FILENO, &oldattr );     newattr = oldattr;     newattr.c_lflag &= ~( ICANON );     tcsetattr( STDIN_FILENO, TCSANOW, &newattr );     ch = getchar();     tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );     return ch; } 

Hope this helps. Please let me know if any error is found.

[Update:] However there is a library in gcc for some other similar functions of "conio.h", which is known as NCURSES library. Thanks to Muhammad Ridowan for letting me know this.


Thursday, October 22, 2009

Linux : Bash Script (Shell Script)


A very simple automatic judge:



All of you studying cse must have known what is an Onlinejudge and most of us don't know how it works. Btw, I'm not going to talk about that here. It's a simple Linux Shell Scripting example / tutorial which will show you how to handle other programs in Bash and how to access all the files in a specific folder not knowing exactly how many are there.

The following snippet works very simply. It takes a target [.cpp] file as a command line argument and compiles it using g++, generates output files for all the input files provided with. And last, it compares those files with original output files and checks whether your program generated all the outputs correctly. So you can use it for your own purposes by making proper modification. It's also very easy to understand.

Note:
The folder from where you run this script must have these in it:
1. in // it will contain the input files with [.in] extension.
2. pout // it will hold the output files generated by your program.
3. jout // it will contain the correct judge output files for testing.
4. The program you are checking for with obviously [.cpp] extension and it's name is to be passed by command line argument.
Unless you change them in the code as you like. It is always a good practice to experiment with codes. :)


# Author: Zobayer Hasan
# CSE DU - 22/10/2009

# Check whether target file is provided or exists
# If available, compile and make it executableclear

if [ $# != 1 ]; then
echo "parameter missing"
exit
elif [ ! -f "$1" ]; then
echo "file not found"
exit
else
if [ -f PROG ]; then
rm PROG
fi

g++ -o PROG "$1"

if [ ! -f PROG ]; then
echo "Compilation Error!"
echo "Your program could not be compiled."
echo ;
exit
fi

chmod -c 777 PROG > log.txt
fi

# Run the executable for each file in the "in" directory
# And generate their output files in "pout" directory
# Then match with the correct files in "jout" directory

echo ;

N=0
values=$( ls ./in/*.in )

for LINE in $values
do
./PROG < "$LINE" > "./pout/$N.out"
diff ./pout/$N.out ./jout/$N.out > log.txt

if [ $? -eq 1 ]; then
echo "Wrong Answer!"
echo "For file $LINE. Check log file."
echo ;
exit
fi

N=$(( N + 1 ))
done

echo "Accepted!"
echo "All tests passed successfully."
echo ;

# End of script :)

Have fun with bash !!!