Saturday, June 23, 2012

SIGPWR

Its been quite a long time since i came out here. Yeah i've been busy with some other work and couldn't really focus on posting anything here.

But i am here aren't I and yeah ive got something new.

Its about linux system calls and signal handling. This simple piece of code was originally a part of a assignment that i was supposed to do.

Basically what it does it prompts the user to create a file by entering a filename at the beginning. And then the the program goes about finding the sum of 1 to 1000. Yes this doesn't take up much time but ive slowed it down using the sleep command. And this program will ensure that whenever the program receives a SIGPWR interrupt the program will write the the proceeds of the summation to the above created file.

To make stuff more interesting here the summation is handled by 10 threads running simultaneously. Each thread sums up 100 mumbers and finally those subtotals are added up to form the final answer.

Interesting enough?

here's the code for the magic.


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>

#define ARRAYSIZE 1000
#define THREADS 10

void *slave(void *myid);

/* shared data */
int data[ARRAYSIZE]; /* Array of numbers to sum */
int sum = 0;
pthread_mutex_t mutex; /* mutually exclusive lock variable */
int wsize;          /* size of work for each thread */ 
int low0,low1,low2,low3,low4,low5,low6,low7,low8,low9;
int i0,i1,i2,i3,i4,i5,i6,i7,i8,i9;
int myresult=0,myresult0=0,myresult1=0,myresult2=0,myresult3=0,myresult4=0,myresult5=0,myresult6=0,myresult7=0,myresult8=0,myresult9=0;
FILE *file;
char fname[100];
/* end of shared data */

void *slave(void *myid){

  int high;
switch((int)myid){
    case 0 :
      low0 = (int) myid * wsize;
      high = low0 + wsize;
      for (i0=low0;i0<high;i0++){
        myresult0 += data[i0];
            sleep(2);}
        myresult=myresult0;
        break;
    case 1 :
      low1 = (int) myid * wsize;
      high = low1 + wsize;
      for (i1=low1;i1<high;i1++){
        myresult1 += data[i1];
            sleep(2);}
        myresult=myresult1;
        break;
    case 2 :
      low2 = (int) myid * wsize;
      high = low2 + wsize;
      for (i2=low2;i2<high;i2++){
        myresult2 += data[i2];
            sleep(2);}   
        myresult=myresult2;   
        break;
    case 3 :
      low3 = (int) myid * wsize;
      high = low3 + wsize;
      for (i3=low3;i3<high;i3++){
        myresult3 += data[i3];
            sleep(2);}
        myresult=myresult3;
        break;
    case 4 :
      low4 = (int) myid * wsize;
      high = low4 + wsize;
      for (i4=low4;i4<high;i4++){
        myresult4 += data[i4];
            sleep(2);}
        myresult=myresult4;
        break;
    case 5 :
      low5 = (int) myid * wsize;
      high = low5 + wsize;
      for (i5=low5;i5<high;i5++){
        myresult5 += data[i5];
            sleep(2);}
        myresult=myresult5;
        break;
    case 6 :
      low6 = (int) myid * wsize;
      high = low6 + wsize;
      for (i6=low6;i6<high;i6++){
        myresult6 += data[i6];
            sleep(2);}
        myresult=myresult6;
        break;
    case 7 :
      low7 = (int) myid * wsize;
      high = low7 + wsize;
      for (i7=low7;i7<high;i7++){
        myresult7 += data[i7];
            sleep(2);}
        myresult=myresult7;
        break;
    case 8 :
      low8 = (int) myid * wsize;
      high = low8 + wsize;
      for (i8=low8;i8<high;i8++){
        myresult8 += data[i8];
            sleep(2);}
        myresult=myresult8;
        break;
    case 9 :
      low9 = (int) myid * wsize;
      high = low9 + wsize;
      for (i9=low9;i9<high;i9++){
        myresult9 += data[i9];
            sleep(2);}
        myresult=myresult9;
        break;
}

  /*printf("I am thread:%d low=%d high=%d myresult=%d \n",(int)myid, low,high,myresult);*/

  pthread_mutex_lock(&mutex);
  sum += myresult;  /* add partial sum to local sum */
    pthread_mutex_unlock(&mutex);
  return;
}

void write(){
    printf(" ***Interrupt system call received. \n Will write computational data into %s\n",fname);
    fprintf(file,"The sum from %d to %d is %d\n",low0,i0,myresult0);
    fprintf(file,"The sum from %d to %d is %d\n",low1,i1,myresult1);
    fprintf(file,"The sum from %d to %d is %d\n",low2,i2,myresult2);
    fprintf(file,"The sum from %d to %d is %d\n",low3,i3,myresult3);
    fprintf(file,"The sum from %d to %d is %d\n",low4,i4,myresult4);
    fprintf(file,"The sum from %d to %d is %d\n",low5,i5,myresult5);
    fprintf(file,"The sum from %d to %d is %d\n",low6,i6,myresult6);
    fprintf(file,"The sum from %d to %d is %d\n",low7,i7,myresult7);
    fprintf(file,"The sum from %d to %d is %d\n",low8,i8,myresult8);
    fprintf(file,"The sum from %d to %d is %d\n",low9,i9,myresult9);
 /*writes*/
  fclose(file); /*finished writing*/
   
}

main(){

  int i;
  pthread_t tid[THREADS];

  pthread_mutex_init(&mutex,NULL); /* initialize mutex */

  wsize = ARRAYSIZE/THREADS;       /* wsize must be an integer */

  for (i=0;i<ARRAYSIZE;i++)        /* initialize data[] */
    data[i] = i+1;

  /* Create file */
 
  printf(" Enter file name here : ");
  fgets(fname, sizeof fname, stdin);
  file = fopen(fname,"w+"); /* apend file (add text to a file or create a file if it does not exist.*/

    pid_t main = getpid();
    printf(" The process id of the main process is %d \n",main);

    signal(SIGPWR,write);

  for (i=0;i<THREADS;i++) /* create threads */
    if (pthread_create(&tid[i],NULL,slave,(void *)i) != 0)
      perror("Pthread_create fails");

  for (i=0;i<THREADS;i++) /* join threads */
    if (pthread_join(tid[i],NULL) != 0)
      perror("Pthread_join fails");

  printf(" The sum from 1 to %i is %d\n",ARRAYSIZE,sum);
}



As you can see theres no magic involved. Its just simple threads and signal handling.

Enjoy !!!

Thursday, February 16, 2012

Malloc Assignment


NEWMALLOC AND NEWFREE ALGORITHM
This will implement an alternate version of malloc and free. For demonstration purposes a character array of 50,000 will be used as the memory to be allocated. Out of that the first 12 bytes will be used as the storage space for the header, which will be the starting point of the linked list storing the allocated nodes.
Each node will have 3 attributes
  • Next – The pointer to the next node
  • Size – The size requested by the caller
  • Address – the array cell value in which the node begins

NewMalloc

NewMalloc will require the number of bytes that needs to be allocated to be passed. Then it will search for the first suitable location for the new node to be inserted. When the sufficient amount of continuous space is found the node will be inserted at that point.
If this is at the end of the linked list the new node will be simply inserted as the last node of the linked list and if it is in between two nodes, the links will be adjusted appropriately and the new node will be inserted.

The allocation uses the first fit basis.

FIRST FIT
First fit is when the node will be inserted at the first available spot. The search will stop when a continuous amount of free array cells are available big enough for the node head and the space requested by the caller. There may be spaces which are much more suitable later in the array, but this will ignore that.
This was chosen because mainly if best fit was selected it will spend a large amount of time looking for the best location in many iterations. Best fit will search the array for space that is equal to the requirement, and then one more than the requirement and so on until the necessary array space is found. This will require many iterations in most cases which will simply be a waste of time. So for increased efficiency first fit was chosen.

NewFree

The freeing method will simply identify the node to which the pointer refers to, and then remove it from the array. If the node is at the end of the linked list it will simply set the previous node as the linked list’s end. If it is in between two nodes the node will be removed linking the previous and next nodes together.

This algorithm will not maintain a separate linked list for free nodes. The free spaces available between nodes will be calculating the difference of the node pointers. This will eliminate internal fragmentation thus a need for defragmentation will not exist.


NEWMALLOC AND NEWFREE CODE

The code segment will contain only the Newmalloc and NewFree fucntions. the main function will need to be added.

The header part needs to be in a separate file named myheader.h

HEADER-

#ifndef _header_
#define _header_

void *NewMalloc(size_t);
void NewFree(void *);

#endif
CODE-

#include <sys/time.h>
#include <stdio.h>
#include "myheader.h"

#define MAXMALLOCSIZE 100
#define MAXMALLOC 10

void *myMalloc(size_t);
void myFree(void *);
void* insert(size_t,node *);
void print();


int main () {

    void  *ptr[MAXMALLOC] = {NULL};
    int i;
    while (1) {
        for (i=0;i<MAXMALLOC;i++){
            int r = random()%2;
            if (r==0){
                if (ptr[i]!=NULL){
                    myFree(ptr[i]);
                    ptr[i] = NULL;
                } else {
                    size_t t = random()%MAXMALLOCSIZE;
                    char *c = myMalloc(t);
                    ptr[i] = (void *) c;
                    if (ptr[i] == NULL) {
                        printf("not enough space!\n");
                        return 0;
                    }
                    //printf("writing %lu\n",t);
                    while (t>0){
                        *c = 0xFF;
                        c++;
                        t--;
                    }
           
                }
            }
        }
    }
    return 0;
}


void *myMalloc(size_t size){
    initialize();
    char *address;
    int check=1;
    //check if array size is exceeded
    if( size+12 > 1000){
        printf("Cannot allocate memory\n");   
        return NULL;
    }else{
       
        node* temp;
        temp=(node *) full_head;
       
        while((*temp).next!=NULL && check==1){
            printf("aawa\n");
            //check if free space available between allocated nodes
            int x1=(int)(*temp).next-(int)temp;
            int x2=(*temp).size+size+24;
            if(x1>x2){
                printf("allocate : %d\n",size);
                address=insert(size,temp);
                check=0;
            }
            temp=(*temp).next;
        }
       
        //check if remaining nodes enough to allocate
        if(check==1 && (int)temp-(int)full_head+(*temp).size+size+12<1000){
            address=insert(size,temp);
        }
       
        return address;
    }
}

void *insert(size_t size, node* current){
    node *temp;
    //calculate relavant array cell
    int position=((int)current)-((int)full_head)+(*current).size+12;
   
    temp=(node*)&array[position];
    (*temp).address=position;
   
    if((*current).next!=NULL){
        node *next = (*current).next;
        (*current).next=temp;
        (*temp).next=next;
        (*temp).size=size;
    }else{
        (*current).next=temp;
        (*temp).size=size;
        (*temp).next=NULL;
    }
   
    position= position+12;
    printf("Node created\n");
    return &array[position];
}

void myFree(void *ptr){
    if(ptr== NULL){
        printf("NULL pointer\n");
    }else if(ptr < 0){
        printf("Irrelavant pointer\n");
    }else{
        //check=0 means that there are no nodes connected
        //check=1 means that there are nodes connected to the header
        int check=0;
        int position = (int)ptr-(int)full_head-12;
               
        node* temp;
        node* prev;
        temp=(node *) full_head;
       
        while((*temp).next!=NULL && (*temp).address!=position){
            check=1;
            prev=temp;
            temp=(*temp).next;
        }
       
        if(check==0){
            (*full_head).next=NULL;
        }else{
            printf("free position : %d\n",(*temp).address);
            node* next=(*temp).next;
            (*prev).next=next;
        }
    }
}

void print(){
    node* temp;
    temp=(node *) full_head;
       
    while((*temp).next!=NULL){
        printf("start : %d\n",(*temp).address);
        printf("size : %d\n", (*temp).size);
        printf("end : %d\n\n",(*temp).address+(*temp).size+12);
        temp=(*temp).next;
    }
    printf("start :%d\n",(*temp).address);
    printf("size : %d\n", (*temp).size);
    printf("end : %d\n\n",(*temp).address+(*temp).size+12);
    printf("---------------------------------------------------------\n");
}

Wednesday, February 8, 2012

Shell alternate implementation in C

Introduction

This is the code in which a alternate shell is implemented.


This version of shell is implemented at the very basic level and  does not have the following features.
  • cd command
  • " " when accessing files and folder 
These features will be implemented in future versions.

Important to remember when operating :
  • To set environmental path variable type 'PATH' which will then ask you to type in the path separately. This will not replace the $PATH variable contents but append to its content.
  • To exit mosh type 'exit'

The Algorithm

First this will read the user command character by character. When the user inputs a command, the last letter or rather the last character will be a enter character (\n). So first this character will be replaced by a null character.This will be helpful especially when searching for the end of the command.

Then it will check for any sign of a pipe command. A character by character search is done and if '|' is found inside the command then it will be split into two arrays from that point onwards. This is to make sure that two different arrays can be passed into the child and parent processes.

Then the characters in the array or arrays will be tokenized using the space ( this will break the characters into words) and store the tokenized characters (separate words) into an array. Then simply depending on if its a pipe command or not it will be passed to the relevant execution methods.

The Code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>

char cmd[50];
char cmd2[50];
char *retrn[10];
char *retrn2[10];
int control=1;


//---------------------------------------------------------------------
main()
{
    printf("\n\n\n ------------ ");
    printf(" My Own SHell ");
    printf(" ------------ \n\n\n");
    readInput();
}
//-----------------------------------------------------------------------
keep(){
    if (control==1 || control ==0){
        if(fork()){
            wait();
            readInput();
        }else{
            if (control==1)
                command();
            else if(control==0)
                pipe_command();
        }
    }else{    
        if(control==4){
            set_path();
        }
        else     if (control ==3)
                printf("MOSH will now exit. \n\n");   
            else
                readInput();
    }
   
}

//-----------------------------------------------------------------------

readInput(){
    memset(&cmd[0], 0, sizeof(cmd));
    memset(&cmd2[0], 0, sizeof(cmd2));
    control = 1;
    printf("\n[ MOSH ] $ ");
    if ( fgets(cmd, sizeof cmd, stdin) != NULL ){
        //remove the newline after each line
        char *newline = strchr(cmd, '\n');
        if ( newline != NULL ){
            *newline = '\0';
        }
        //serach for | and determine pipe commands
       
        char *pipe = strchr(cmd, '|');
        if( pipe != NULL){
            control=0;
            // split array and store commands after | into second array
            *pipe= '\0';
            pipe=pipe+1;
            strcpy(cmd2,pipe);
        }
    }

   
       
        int count=0;
        char delims[] = " ";
        char *result = NULL;
        result = strtok( cmd, delims );
        // look for command exit
        if(strcmp(cmd,"exit") == 0)
            control=3;
        //look for path setting command
        if(strcmp(cmd,"PATH") == 0)
            control=4;
        while( result != NULL ) {
             retrn[count]=result;
                result = strtok( NULL, delims );
            count+=1;
        }
        count=0;
        result = strtok( cmd2, delims );
        while( result != NULL ) {
             retrn2[count]=result;
                result = strtok( NULL, delims );
            count+=1;
    }
    keep();
}

//-----------------------------------------------------------------------

command(){       
    execvp(retrn[0],retrn);
}

//-----------------------------------------------------------------------

pipe_command(){
    //execute pipe command
    int pfds[2];
    pipe(pfds);
    if (!fork()) {
        close(1);      
        dup(pfds[1]);  
        close(pfds[0]);
        execvp(retrn[0],retrn);
    } else {
        close(0);     
        dup(pfds[0]);  
        close(pfds[1]);
        execvp(retrn2[0],retrn2);
    }   
}

//-----------------------------------------------------------------------
set_path(){
    char* pathvar=getenv("PATH");;
    printf("          Enter Path variable : ");
    fgets(cmd, sizeof cmd, stdin);
    char* path=malloc(sizeof(char)* (strlen(pathvar)+strlen(cmd)+2));
    path=strcat(path,pathvar);
    path=strcat(path,":");
    path=strcat(path,cmd);
    path=strcat(path, "\0");
       setenv("PATH",path,1);
    free(path);
    readInput();
}

Hope you enjoy !!!! :D :D