Friday 31 August 2012

example of char device driver

--------------------
 char_dev.c
--------------------

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h> // required for various structures related to files liked fops.
#include <asm/uaccess.h> // required for copy_from and copy_to user functions
#include <linux/semaphore.h>
#include <linux/cdev.h>
static int Major;
dev_t dev_no,dev;
struct device
{
char array[100];
struct semaphore sem;
}char_dev;

int open(struct inode *inode, struct file *filp)
 {
        printk(KERN_INFO "Inside open \n");
        if(down_interruptible(&char_dev.sem)) {
        printk(KERN_INFO " could not hold semaphore");
        return -1;
  }
 return 0;
}

int release(struct inode *inode, struct file *filp)
 {
        printk (KERN_INFO "Inside close \n");
        printk(KERN_INFO "Releasing semaphore");
        up(&char_dev.sem);
        return 0;
}

ssize_t read(struct file *filp, char *buff, size_t count, loff_t *offp)
{
       unsigned long ret;
       printk("Inside read \n");
       ret = copy_to_user(buff, char_dev.array, count);
       return ret;
}

ssize_t write(struct file *filp, const char *buff, size_t count, loff_t *offp)
{
       unsigned long ret;
       printk(KERN_INFO "Inside write \n");
       ret = copy_from_user(char_dev.array, buff, count);
       return count;
}

struct file_operations fops = {
 read:  read,
 write:  write,
 open:   open,
 release: release
};

struct cdev *kernel_cdev;

int char_dev_init (void)
{
      int ret;
      kernel_cdev = cdev_alloc();
      kernel_cdev->ops = &fops;
      kernel_cdev->owner = THIS_MODULE;
      printk (" Inside init module\n");
      ret = alloc_chrdev_region( &dev_no , 0, 1,"chr_arr_dev");
      if (ret < 0) {
      printk("Major number allocation is failed\n");
      return ret;
 }

Major = MAJOR(dev_no);
dev = MKDEV(Major,0);
sema_init(&char_dev.sem,1);
printk (" The major number for your device is %d\n", Major);
ret = cdev_add( kernel_cdev,dev,1);
if(ret < 0 )
{
     printk(KERN_INFO "Unable to allocate cdev");
     return ret;
}
     return 0;
}

void char_dev_cleanup(void)
{
     printk(KERN_INFO " Inside cleanup_module\n");
     cdev_del(kernel_cdev);
     unregister_chrdev_region(Major, 1);
}

MODULE_LICENSE("GPL");
module_init(char_dev_init);
module_exit(char_dev_cleanup);
-------------
Makefile :
-------------

ifneq ($(KERNELRELEASE),)
   obj-m := char_dev.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif

----------------
creating a node:
----------------
mknod /dev/char_dev c 250 0



User Application :-
-------------------
main.c
------------------

#include <stdio.h>
#include <fcntl.h>

main ( )
 {
        int i,fd;
        char ch, write_buf[100], read_buf[100];
        fd = open("/dev/char_dev", O_RDWR);
        if (fd == -1)
        {
                printf("Error in opening file \n");
                exit(-1);
        }
        printf ("Press r to read from device or w to write the device ");
        scanf ("%c", &ch);

        switch (ch) {
                case 'w':
                       printf (" Enter the data to be written into device");
                        scanf (" %[^\n]", write_buf);
                        write(fd, write_buf, sizeof(write_buf));
                        break;
                case 'r':
                        read(fd, read_buf, sizeof(read_buf));
                        printf ("The data in the device is %s\n", read_buf);
                        break;
                default:
                        printf("Wrong choice \n");
                        break;
        }
        close(fd);
}
------------------------------
Compiling User Application :
------------------------------
$gcc -o main main.c

#./main
Press r to read from device or w to write the device : w
Enter the data to be written into device  : American Megatrends Inc.

#./main
Press r to read from device or w to write the device : r
The data in the device is : American Megatrends Inc.

Thursday 30 August 2012

Forgot Root Password


I think this must be a common problem to a lot of users, forgetting the root password of their system or in the case of New ubuntu like systems that do not have a root log in, if you forget the password for the only user in your system then you are stuck with no way of logging in. Well there is simple work around for situations like this.
Follow the following steps to reset your root password. [Please see below for ubuntu systems]

1. While your system boots go the GRUB menu by pressing "esc".
2. Highlight the OS you want to boot using the arrow keys.
3. Press "e"
4. You will see three options ( generally), move to the line that starts with "kernel".
5. press "e" again
6. You will see a line of text, move to the end of it.
7. Add "single" or "1" to the end of the line.
8. Hit Enter and press "b".

Your system should boot into a text mode, with a shell prompt.

typer  "passwd" and hit enter.
You will be prompted for a new password. enter the password , you will be asked for confirmation enter the password again.

enter the command "reboot" and hit enter.

The system should boot back to your normal log in screen, you can use the new password that you just set for the root log in.

In case of Ubuntu systems this method does not work very well so there is slightly different way of making it work.
in step 7: instead of adding "1"  add the text "/dev/sda=rw"  assuming sda is the partition on which you have your Linux installed.

Hope you are able to log into your system again :-)

User is not in the sudoers file. This incident will be reported

On using the sudo command if we see the error message:
 
"User is not in the sudoers file. This incident will be reported."

This means that the user as whom we have logged in and are trying to run the command "sudo" does not have the permission to do so.
Only the users listed in /etc/sudoers have the permission to use the command "sudo".
To give the sudo permission to a user we need to add the user to the file /etc/sudoers file.
Open the file /etc/sudoers as root.
 
$sudo vim /etc/sudoers

Add the line
 
username ALL = (ALL) ALL

under the User privilege specification section.
Save the file and exit, now the sudo command should work for the user which was added in the file.

How to get Motherboard details



We can find out all the details about the motherboard in our system using the command lshw.
#lshw -class bus |grep -A 6 Motherboard
       description: Motherboard
       product: DH55TC
       vendor: Intel Corporation
       physical id: 0
       version: AAE70932-302
       serial: BTTC10900DL8
       slot: To be filled by O.E.M.

Inter Process Communication using shared memory


Processes can communicate between each other in various ways, one of the techniques is by using shared memory, i.e. the processes share a memory region between each other which both can read from. Processes can read and write from this memory what ever that has to be shared.

To create or get access to an already created shared memory we use the function shmget (shared memory get).

int shmget(key_t key, size_t size , int shmflg);

Arguments: key : The key used by the process to identify the shared memory, it is assigned by the process and the other processes which want to communicate with this shared memory need to know this key.

size: The size of the shared memory that is allocated.

flag: If the shared memory is being created then we can use the flag IPC_CREAT as the flag. If we are trying the get access to a shared memory already created then we can pass the mode flag specifying the rights for owner,group and the world in the same format as followed by "chmod".

Return : An identifier to the shared memory which is used along with the "key" to identify the memory segment for communication.

Once the share memory is allocated to start the communication we need forts attach this shard memory with the memory of the process to this we use the function shmat (shared memory attach)


void * shmat(int shmid,const void *shmaddr , int shmflg);

Arguments:

shmid: The identifier returned by shmget

shmaddr: The address where the segment should get attached, if left NULL the system automatically chooses a suitable location for the attach.

shmflg: Used in the specific case when mapping of the segment should replace any existing mapping in the range starting at shmaddr , can be left NULL otherwise.

Return: The address of the shared memory that was attached to the process.

Once the memory segment is attached data can be read from and written to the shared memory using the address returned by shmat and the the functions sscanf and sprintf respectively.

Example:

The following program creates a shared memory in the default mode and then writes a message in the shard memory.

Note the used of IPC_CREAT flag with the shmget call.

write_shm.c
------------------------------------------------------------------------------------------------------------
#include <sys/ipc.h>
#include<sys/shm.h>
#include <stdio.h>
main()
{
key_t key=12345;
int shm_id;
void *shm;
char *message="hello";
shm_id =shmget(key,10*sizeof(char),IPC_CREAT);
shm = shmat(shm_id,NULL,NULL);
sprintf(shm,"%s",message);
}
------------------------------------------------------------------------------------------------------------


The following code tries access the shared memory created by the above code and read the data written in it. Note that the value of key used by both the codes are same, failing which the shmget will be unable to identify the shared memory.


 read_shm.c
------------------------------------------------------------------------------------------------------------
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
main()
{
key_t key=12345;
int shm_id;
void *shm;
char *message;
message=malloc(10*sizeof(char));
shm_id=shmget(key,10*sizeof(char),NULL);
shm=shmat(shm_id,NULL,NULL);
if(shm == NULL)
{
printf("error");
}
sscanf(shm,"%s",message);
printf("\nmessage=%s\n",message);
}
------------------------------------------------------------------------------------------------------------


Compile the above programs
Compile the above programs

$gcc write_shm.c -o write_shm
$gcc read_shm.c -o read_shm

execute them

$./write_shm
$./read_shm
Message = hello

You should see the message written by the first process displayed by the second process thus achieving the required communication between the processes.