Table of Contents

Part 2

Entries

October 3, 2011

I updated my linked list development, and committed it to the Subversion repository.
There is an

lab46:~/src/data$ svn commit -m "Updated linkedLinst1-jr.c to include delete node, append, ans insert. Thes functions need work as they do not handle the end  node or the  next to end node correctly -jr"
Sending    data/linkedList1-jr.c
Transmitting file data .
Committed revision 10.

October 6, 2011

After verifying my linked list library, I then added the linkedListLibrary directory and its files to the Subversion repository.

lab46:~/src/data$ svn add linkedListLibrary
A         linkedListLibrary
A         linkedListLibrary/linkedListLib.c
A         linkedListLibrary/linkedList-jr.c
A         linkedListLibrary/linkedListLib.h
A         linkedListLibrary/linkedListTest.c
A  (bin)  linkedListLibrary/linkedListTest
lab46:~/src/data$

After adding the linked list library files to the Subversion repository, I committed them as well.

lab46:~/src/data$ svn commit -m "linked list library, linkedListLib.a, contains the following functions: createList, destroyListHead, destroyListTail, listSizeHead, listSizeTail, printIntDataHead, insert, append, deleteNode, void loadListData, loadNode, createNode, copyList, findData, which have all been verified -John Rine"                                                                                                                                                          Sending        data/linkedList1-jr.c
Adding         data/linkedListLibrary
Adding         data/linkedListLibrary/linkedList-jr.c
Adding         data/linkedListLibrary/linkedListLib.c
Adding         data/linkedListLibrary/linkedListLib.h
Adding  (bin)  data/linkedListLibrary/linkedListTest
Adding         data/linkedListLibrary/linkedListTest.c
Transmitting file data ......
Committed revision 11.
lab46:~/src/data$

I am now finalizing my linked list project page which is at:
http://lab46.corning-cc.edu/user/jr018429/portfolio/libdll .

October 12, 2011

I learned to use a single .h file to prototye all of my functions and the node structure for all of my library files. Below is a record of the steps I went through to get there.
I successfully created and used a static linked list library, or so I thought, when I finalized my linked list project. However, when it came to implementing a static library of stack routines and associated data type, I had a horrible time. every library file wanted a node structure in it however when I linked the library files together, I got error messages! I had to figure out a way to have only one node struct reference that I could share with the library files. I appealed to the instructor for help!

Date: Wed, 12 Oct 2011 19:54:26 -0400 (EDT)
From: John Rine <jr018429@lab46.corning-cc.edu>
To: wedge@lab46.corning-cc.edu, haas@corning-cc.edu
Subject: static library HELP!!!!!

I am trying to finish my stack library and mange all the crap going on in my personal life and it ain't going very good.
I think I got lucky compiling and linking the linked List library.
I am having a time with the stack. I took a different approach with it.
I am having many library files with names describing the functions inside.
For example:
createFixedStack.c createFixedStack.h
listStackSize.c
listStackSize.h
destroyFixedStack.c
destroyFixedStack.h

I also have a test program named:
stackTest.c

please look closely at the #include "..." in the files, also look closely at the way I created the static library.
What am I doing wrong?????
I can't find any good examples on the Internet. My issues are compounded by having a struct. please look closely at how the struct is included in the includes.

I took copious notes. From you class, I got:
main
#include "mything.h"
how does "mything.h in the test program relate to multiple include files??
 I also got the following:
ar rcs libdll.a *.o
How does libdll relate to "mything.h" in the test program?
I am missing something!!!!

in stackTest.c I am declaring the individual .h files:
#include "createFixedStack.h"
#include "destroyFixedStack.h"
#include "listStackSize.h"

I successfully created .o files for these libraries using the following:
lab46:~/Stack$ gcc -c createFixedStack.c -o  createFixedStack.o
lab46:~/Stack$ gcc -c destroyFixedStack.c -o  destroyFixedStack.o
lab46:~/Stack$ gcc -c listStackSize.c -o  listStackSize.o

Then I can successfully create a static library using:
lab46:~/Stack$ ar rcs libStackJRdll.a *.o


Code and includes


//createFixedStack.h
//John T. Rine
//October 12, 2011

#ifndef _CREATEFIXEDSTACK_JR_H
#define _CREATEFIXEDSTACK_JR_H

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

struct Node
{
       int data;
       struct Node * prev;
       struct Node * next;
};

typedef struct Node node;


void createFiixedStackList(node **, node **, int);

#endif


//createFixedStack.c
//John T. Rine
//October 12, 2011

#include<stdlib.h>
#include<stdio.h>
#include"createFixedStack.h"



void createFixedStack(node **head, node **tail, int elements)
{
       int i;
       node *new;
       new = NULL;
       *head = *tail = NULL;

       for(i = 1; i<=elements; i++)
       {
               if (*head == NULL)
               {
                       *head = (node *) malloc(sizeof(node));
                       *tail = *head;
                       (*head)->prev = NULL;
                       (*head)->next = NULL;
               }
               else
               {
                       new = (node *) malloc(sizeof(node));
                       new->prev = *tail;
                       new->next = NULL;
                       (*tail)->next = new;
                       *tail = new;
               }
       }
}




//destroyFixedStack.h
//John T. Rine
//October 12, 2011

#ifndef _DESTROYFIXEDSTACK_JR_H
#define _DESTROYFIXEDSTACK_JR_H

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

struct Node
{
       int data;
       struct Node * prev;
       struct Node * next;
};

typedef struct Node node;


void destroyFixedStackHead(node *);
void destroyFixedStackTail(node *);

#endif



//destroyFixedStack.c
//John T. Rine
//October 12, 2011

#include<stdlib.h>
#include<stdio.h>
#include "destroyFixedStack.h"

void destroyFixedStackHead(node *head)
{
       node *temp;
       node *temp2;
       temp = NULL;
       temp2 = NULL;
       temp = head;
       while(temp != NULL)
       {
               temp2 = temp->next;
               if (temp->prev != NULL) temp->prev = NULL;
               if (temp->next != NULL) temp->next = NULL;
               free(temp);
               temp = temp2;
       }
}

void destroyFixedStackTail(node *tail)
{
       node *temp;
       node *temp2;
       temp = NULL;
       temp2 = NULL;
       temp = tail;
       while(temp != NULL)
       {
               temp2 = temp->prev;
               if (temp->prev != NULL) temp->prev = NULL;
               if (temp->next != NULL) temp->next = NULL;
               free(temp);
               temp = temp2;

       }
}



//listStackSize.h
//John T. Rine
//October 12, 2011

#ifndef _LISTSTACKSIZE_JR_H
#define _LISTSTACKSIZE_JR_H

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

struct Node
{
       int data;
       struct Node * prev;
       struct Node * next;
};

typedef struct Node node;

int listStackSizeHead(node *);
int listStackSizeTail(node *);

#endif


//listrStackSize.c
//John T. Rine
//October 12, 2011


#include<stdlib.h>
#include<stdio.h>
#include"listStackSize.h"

int listStackSizeHead(node *head)
{
       int size = 0;
       while (head != NULL)
       {
               head = head->next;
               size++;
       }
       return size;
}

int listStackSizeTail(node *tail)
{
       int size = 0;
       while (tail != NULL)
       {
               tail = tail->prev;
               size++;
       }
       return size;
}



//stackTest.c
//Author: John T. Rine
//Date: October 12, 2011


#include "createFixedStack.h"
#include "destroyFixedStack.h"
#include "listStackSize.h"

int main(int argc, char **argv)
{

       node *head, *tail;
       head = tail = NULL;

       printf("Creating a list of 10 nodes...\n");
       createFixedStack(&head, &tail, 10);
       getchar(); //Holds the console window open on a Windows machine
}






However when I try to create the test executable, it bombs-HELP!!!

John T. Rine

Graduate Electrical Technology-Electronics
Graduate General Studies
---
 Lab46: Penguin Powered

October 13, 2011

I finally figured that I could create a struct .h file to define the node structure and then include that .h file in my lother library files. Sure enough, it worked!

Date: Thu, 13 Oct 2011 10:40:10 -0400
From: Matthew Haas <wedge@lab46.corning-cc.edu>
To: John Rine <jr018429@lab46.corning-cc.edu>
Subject: Re: static library HELP!!!!! (fwd)
On Oct 12, 2011, at 11:34 PM, John Rine wrote:


      I got it.
      The issue is that the structure used as a node is shared throughout all of the functions. When you break them up, you can't include the structure in
      every .h file, so what you do is to creat e a structure.h file and include that in the broken up files. Its seems you also need it in the test file as
      well. Man did that was driving me crazy.

</cli> My instructor pointed out, however, that I could have simply made one .h file for all of my library files! Why didn't I think of that?

Date: Thu, 13 Oct 2011 10:40:10 -0400
From: Matthew Haas <wedge@lab46.corning-cc.edu>
To: John Rine <jr018429@lab46.corning-cc.edu>
Subject: Re: static library HELP!!!!! (fwd)
Parts/Attachments:
   1   OK    ~61 lines  Text
   2 Shown   ~62 lines  Text
----------------------------------------


On Oct 12, 2011, at 11:34 PM, John Rine wrote:


      I got it.
      The issue is that the structure used as a node is shared throughout all of the functions. When you break them up, you can't include the structure in
      every .h file, so what you do is to creat e a structure.h file and include that in the broken up files. Its seems you also need it in the test file as
      well. Man did that was driving me crazy.


John,

 You may have appeared to resolve the issue, but I think the situation is still inordinately complex and can be simplified.

 For your stack library, you should be able to get away with just 1 header file, let's call it: stack.h

 stack.h can look as follows:

-------------------------------------
#ifndef _STACK_H
#define _STACK_H

#include "linkedlist.h"

struct stack {
struct list *data;
struct node *top;
};
typedef struct stack Stack;

Node *pop(Stack *);
int push(Stack *, Node *);
Node *peek(Stack *);
int isEmpty(Stack *);

#endif
-------------------------------------

All your .c files can just #include "stack.h", which will take care of all the function prototypes, struct definition, and even pull in the linked list stuff for
you (the linkedlist.h file will similarly have #ifndef _LINKED_LIST_H guards).

With so many header files, the way you seem to be approaching it might be creating a lot more managerial work for yourself... let the preprocessor take care of it
for you.

Is this code on Lab46? I took a quick peek and couldn't find it.

-Matthew
--
Matthew Haas
Lab46 System Administrator
Instructor of Computer & Information Science
http://lab46.corning-cc.edu/haas/home/ [lab46.corning-cc.edu]

October 14, 2011

I finally finished my doubly linked stack library project :) !!! It is available at:
http://lab46.corning-cc.edu/user/jr018429/portfolio/stack
I learned about implementing stacks using doubly linked structure node structures. I also learned how to use a single .h file for all library function prototypes and the library node structure definition. I also learned that another more complicated way of implementing the library would be to create a strucure .h file which defines the node structure and then including that in the other library files, assuming one is using a .h file per library .c file. Yet another way might be to include the node structure definition in each .h file but wrap it in a #ifndef, #define, #endif block as follows:

#ifndef _NODESTRUCT_H
#define _NODESTRUCT_H
struct Node
{
        int data;
        node *next;
        node *prev;
}
#endif

October 19, 2011

State machines are ubiquitous in programming and in hardware design-synchronous digital logic design. I found a very good tutorial on statemachine design at: http://johnsantic.com/comp/state.html . I shared this link and what I know about state-machines with my Data Structures and Systems Programming classes.

Date: Wed, 19 Oct 2011 23:06:46 -0400 (EDT)
From: John Rine <jr018429@lab46.corning-cc.edu>
To: data@lab46.corning-cc.edu, sys@lab46.corning-cc.edu
Subject: State Machines in Programming

Check out this link on state machines:
http://johnsantic.com/comp/state.html

State machines are a very import concept in both hardware and software design.
Stae machines  are either, in the case of hardware, clock driven or in software, loop, or interrupt driven. State machines store their last state and then compare
this last state to input and if defined in their design, will change state when triggered by a clock, loop, or interrupt.
State machines implemented in software can be used to perform hardware control, for example machine tool and robotics software. Soft state machines can be used in
game design such that game flow changes based on the game's previous state and input from the player. One way to implement state machines in software by combining
loop and  selecttion structures.

In hardware they are implemented using a register (flip-flops) and decoding logic. Why even discuss a hardware implement here? Well as we learned last sememmster in
Computer Organizations, hardware can be simulated in software! The decoding logic of a hardware defined state machine decodes the outputs of the state register
(output and state storage) and input and caauses the state register's state to change when the output state and inputs change to some value defined by the design.
Even though a synchronous counter is not considered to be a state machine, it may be helpful as an analogy to understanding them. A synchronous counter is reset
when firat powered up. The decoding circuitry sees 0 on the out put of the counter and decodes this value to be 1 on the input. On the next clock pulse, the counter
changes to 1 on its output. now the decoding circuitry sees 1 on the output and decodes this to 2 on the input. When the next clock tick occurs, the output changes
to 3 and so on... To get to a state machine from a synchronous counter, simply add inouts from the outside to the ddecoding circuitry. Now consider a hardware state
machine, on power up the state machine's outputs are set to 0. Now if a sensor on an input changes state, when the next clock pulse occurs and if the decoding
circuitry is designed to do so, a state machine output will change in response to the sensor's input. This output will maintain its state until the decoding logic
coupled with certain input states associate with the decoding design and a clock pulse causes it to change.
There are two types of hardware state machines:
1. Moore, and
2. Meally
At least one author has described the cpu as a state machine.
I am sure I have made the subject of state machines as clear as mud.

John T. Rine

Graduate Electrical Technology-Electronics
Graduate General Studies
---
 Lab46: Penguin Powered

October 23, 2011

I added and committed my forkExample.c program to the Subversion repository.

lab46:~/src/sysprog$ svn add forkExample.c
A         forkExample.c
lab46:~/src/sysprog$ svn commit -m "Added and commited a simple example of using fork -John Rine"
Adding         sysprog/forkExample.c
Transmitting file data .
Committed revision 16.

I added and committed my useMalloc.c program to the Subversion repository.

lab46:~/src/data$ svn add useMalloc.c
A         useMalloc.c
lab46:~/src/data$ svn commit -m "Added and committed useMalloc.c, an example program demonstrating dynamic memory allocation of structures and arrays -John Rine"
Sending        data/Stack/libdll.a
Adding         data/useMalloc.c
Transmitting file data ..
Committed revision 17.
lab46:~/src/data$

October 24, 2011

I conducted and documented an experiment to determine if a string literal could be assigned to a pointer pointing to dynamically allocated memory and then be used in a program, then when the data is no longer needed, deallocate it. The experiment is documented in Part II, experiment 1.

October 28, 2011

I added and committed the code I wrote to implement an array-based stack data structure.

lab46:~/src/data$ svn add arrayStack.c
A         arrayStack.c
lab46:~/src/data$ svn commit -m "Added and committed an array-based stack program. -John Rine"
Adding         data/arrayStack.c
Sending        data/useMalloc.c
Transmitting file data ..
Committed revision 18.
lab46:~/src/data$


I added and committed the code I wrote to design and test doubly-linked list functions.

lab46:~/src/data$ svn add linkedListDev.c
A         linkedListDev.c
lab46:~/src/data$ svn commit -m "Added and committed linkedListDev.c, a linked list development program -John Rine"
Adding         data/linkedListDev.c
Transmitting file data .
Committed revision 19.
lab46:~/src/data$

October 29, 2011

I added and committed the code I wrote to learn about threads.

lab46:~/src/sysprog$ svn add threadTest.c
A         threadTest.c
lab46:~/src/sysprog$ svn commit -m "Added and committed threadTest.c a program to illustrate thread creation and termination -John Rine"
Sending        sysprog/interface.c
Adding         sysprog/threadTest.c
Transmitting file data ..
Committed revision 20.
lab46:~/src/sysprog$


I added and committed the code I wrote to implement an array-based queue.

lab46:~/src/data$ svn add queueTest.c
A         queueTest.c
lab46:~/src/data$ svn commit -m "Added and committed an array-based example of a queue -John T. Rine"
Adding         data/queueTest.c
Transmitting file data .
Committed revision 21.
lab46:~/src/data$

October 30, 2011

I entered my part deux (II) course objectives for systems programming and data structures courses. I also completed my third experiment for part II. I also wrote system programming topic information for the synchronization methods mutex, and barrier.

data Topics

malloc

malloc is a c library function for dynamically allocating memory in the “heap”. dynamically allocated memory is memory that has been set aside for use during the execution of the program, also know as “run time”. malloc can be used to dynamically allocate variables as well as arrays, including multidimensional arrays and structures. The malloc function becomes available for use in a program after the stdlib.h header has been added to the program.

useMalloc.c
//useMalloc.c
//John T. Rine
//October 23, 2011
 
#include<stdlib.h>
#include<stdio.h>
 
 
struct Test
{
        char *message1;
        char *message2;
};
 
typedef struct Test test;
 
int main(int argc, char **argv)
{
 
        //malloc a struct
        test *testPTR;
 
        testPTR = (test *)malloc(sizeof(test));
 
        testPTR->message1 = "Hello ";
        testPTR->message2 = "world!";
 
        printf("Message1 = %s, message2 = %s\n", testPTR->message1, testPTR->message2);
 
        free(testPTR);
 
 
        //malloc a char array
        int i = 0;
        int ii = 0;
        char * inputString = "John T. Rine\0";
        char * string = NULL;
 
        printf("input string contains %s\n", inputString);
        while(*(inputString + i) != '\0') i++;
        printf("Character count = %d\n", i);
        string = (char *)malloc(sizeof(char) * (i + 1));
        for(ii = 0; ii <= (i + 1); ii++) *(string + ii) = *(inputString + ii);
        printf("Dynamically allocated array contains %s\n", string);
 
        free(string);
 
        return 0;
}

Compilation and execution of useMalloc.c were successful as seen below.

lab46:~/src/data$ ./useMalloc
Message1 = Hello , message2 = world!
input string contains John T. Rine
Character count = 12
Dynamically allocated array contains John T. Rine
lab46:~/src/data$
References

Heap

Since the data structures class is now making copious use of dynamically allocated memory using malloc and free to allocate and deallocate memory to make, manage, and destroy linked lists, stacks, quesues and so on, wouldn't it be a good idea to understand what the heap is, and how its used?
Dynamically allocated memory is usually allocated from a pool of unused memory known as the “heap” or “free store”. Because the exact memory address of a dynamic memory allocation is not known in advance, dynamically allocated memory is accessed indirectly through the use of pointers. The exact method used to organize the heap and allocate and deallocate parts of it is hidden behind an abstract interface.

References

Stack

The stack is a last in, first out (LIFO) data structure. A stack can have any data type, including structures as elements, but has only a few basic operations which can be performed on it: initialize or create, push, pop and peek. The initialize or create operation creates a stack and initializes it. The push operation adds a new item to the top of the stack. The pop operation removes an item from the top of the stack. The stack peek operation gets the data from the top of the stack without deleting it or changing the stack pointer.

arrayStack.c
//arrayStack.c
//John T. Rine
//October 28, 2011
 
#include<stdio.h>
#include<stdlib.h>
 
struct Stack 
{
  char *array;
  int top;
  int size;
};
 
typedef struct Stack stack;
 
int cntChars(char *);
void createStack(stack *, int);
void push(stack *, char);
char pop(stack *);
int isEmpty(stack *);
int isFull(stack *);
 
int main(int argc, char **argv)
{
	int i;
	int count;
	stack newStack;
	char stringArray[200];
 
	printf("Enter a string: ");
	gets(stringArray); 
	count = cntChars(stringArray); 
	createStack(&newStack, count); 
	if(isEmpty(&newStack)) printf("Stack is empty\n");
	else printf("Stack is not empty\n");
	for(i = 0; i < count; i++)
	{
		push(&newStack,stringArray[i]);
                printf("The character going into tos is: %c\n", newStack.array[i]);
	}
        if(isEmpty(&newStack)) printf("Stack is empty\n");
        else printf("Stack is not empty\n");
	for(i = 0; i < count; i++) printf("The character in tos is: %c\n", pop(&newStack));
        for(i = 0; i < count; i++)
        {
                push(&newStack,stringArray[i]);
                printf("The character going into tos is: %c\n", newStack.array[i]);
        }
	push(&newStack,'H');
 
	return 0;
}
 
int cntChars(char *inputString)
{
	// returned value "count" does not include '\0'
	int count = 0;
	while(*(inputString + count) != '\0') ++count;
	return(count);
}
 
void createStack(stack *stackVar, int size)
{
	char *array;
 
	array = (char *)malloc(sizeof(char) * size);
 
  	if (array == NULL)
	{
    		fprintf(stderr, "Not enough memory to create the stack.\n");
    		exit(1);
  	}
 
	stackVar->array = array;
  	stackVar->size = size;
  	stackVar->top = -1;
 
}
 
int isEmpty(stack *stackVar)
{
  return stackVar->top < 0;
}
 
int isFull(stack *stackVar)
{
  return stackVar->top >= stackVar->size - 1;
}
 
void push(stack *stackVar, char  element)
{
	if (isFull(stackVar))
	{
		fprintf(stderr, "Can't push on the stack is full\n");
		exit(1);
	}
	stackVar->array[++stackVar->top] = element;
}
 
 
char pop(stack *stackVar)
{
	if (isEmpty(stackVar))
	{
		fprintf(stderr, "Can't pop from stack; stack is empty\n");
		exit(1);
	}
	return stackVar->array[stackVar->top--];
}


Execution of the source code listed above with the string “Oh no! I have just been Rick rolled!” as input.

lab46:~/src/data$ gcc arrayStack.c -o arrayStack
/tmp/cczFb9N2.o: In function `main':
arrayStack.c:(.text+0x35): warning: the `gets' function is dangerous and should not be used.
lab46:~/src/data$ ./arrayStack
Enter a string: Oh no! I have just been Rick rolled!
Stack is empty
The character going into tos is: O
The character going into tos is: h
The character going into tos is:
The character going into tos is: n
The character going into tos is: o
The character going into tos is: !
The character going into tos is:
The character going into tos is: I
The character going into tos is:
The character going into tos is: h
The character going into tos is: a
The character going into tos is: v
The character going into tos is: e
The character going into tos is:
The character going into tos is: j
The character going into tos is: u
The character going into tos is: s
The character going into tos is: t
The character going into tos is:
The character going into tos is: b
The character going into tos is: e
The character going into tos is: e
The character going into tos is: n
The character going into tos is:
The character going into tos is: R
The character going into tos is: i
The character going into tos is: c
The character going into tos is: k
The character going into tos is:
The character going into tos is: r
The character going into tos is: o
The character going into tos is: l
The character going into tos is: l
The character going into tos is: e
The character going into tos is: d
The character going into tos is: !
Stack is not empty
The character in tos is: !
The character in tos is: d
The character in tos is: e
The character in tos is: l
The character in tos is: l
The character in tos is: o
The character in tos is: r
The character in tos is:
The character in tos is: k
The character in tos is: c
The character in tos is: i
The character in tos is: R
The character in tos is:
The character in tos is: n
The character in tos is: e
The character in tos is: e
The character in tos is: b
The character in tos is:
The character in tos is: t
The character in tos is: s
The character in tos is: u
The character in tos is: j
The character in tos is:
The character in tos is: e
The character in tos is: v
The character in tos is: a
The character in tos is: h
The character in tos is:
The character in tos is: I
The character in tos is:
The character in tos is: !
The character in tos is: o
The character in tos is: n
The character in tos is:
The character in tos is: h
The character in tos is: O
The character going into tos is: O
The character going into tos is: h
The character going into tos is:
The character going into tos is: n
The character going into tos is: o
The character going into tos is: !
The character going into tos is:
The character going into tos is: I
The character going into tos is:
The character going into tos is: h
The character going into tos is: a
The character going into tos is: v
The character going into tos is: e
The character going into tos is:
The character going into tos is: j
The character going into tos is: u
The character going into tos is: s
The character going into tos is: t
The character going into tos is:
The character going into tos is: b
The character going into tos is: e
The character going into tos is: e
The character going into tos is: n
The character going into tos is:
The character going into tos is: R
The character going into tos is: i
The character going into tos is: c
The character going into tos is: k
The character going into tos is:
The character going into tos is: r
The character going into tos is: o
The character going into tos is: l
The character going into tos is: l
The character going into tos is: e
The character going into tos is: d
The character going into tos is: !
Can't push on the stack is full
lab46:~/src/data$
References
  1. <html><a href=“http://en.wikipedia.org/wiki/Stack_(abstract_data_type)”>http://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a></html>

Linked List

A linked list is a data structure whose elements each contain pointers to other elements in the linked list. There are singly-linked lists whose pointers only point in one direction, and doubly-linked lists which has pointers pointing in the direction of head and pointers which point in the direction of the tail. The list is traversed using the pointers contained in the node.
For example, a list can be traversed from the head using the “next” pointer as follows:

temp = head;
while(temp != NULL)                //while temp is not at the end of the list
{
	printf("%d ",temp->data); //printf the value of the data in the current node
	temp = temp->next;        //load temp with the address of the next node
}


linkedListDev.c
//linkedListDev.c
//John T. Rine
//October 28, 2011
 
 
#include<stdio.h>
#include<stdlib.h>
 
struct Node
{
	int data;
	struct Node * prev;
	struct Node * next;
};
 
typedef struct Node node;
 
void createList(node **, node **, int);
void destroyListHead(node *);
void destroyListTail(node *);
int listSizeHead(node *);
int listSizeTail(node *);
void printIntDataHead(node *);
void insert(node **, node **, int, int);
void append(node **, node **, int, int);
void deleteNode(node **, node **, int);
void loadListData(node *);
void loadNode(node *, int, int);
void createNode(node*, node*);
void copyList(node *, node **, node **);
int findData(node *, int);
 
int main(int argc, char **argv)
{
 
	node *head, *tail, *copyHead, *copyTail, *temp;
	head = tail = copyHead = copyTail = NULL;
 
	int i = 1;
 
	printf("Creating a list of 4 nodes...\n");
	createList(&head, &tail, 4);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printf("Load list data\n");
	loadListData(head);
	printIntDataHead(head);
	printf("Inserting node 0 with data of 3200 before head node...\n");
	insert(&head, &tail, 0, 3200);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Inserting node with data of -3200 before tail node...\n");
	insert(&head, &tail, listSizeHead(head) - 1, -3200);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Appending node with data of 2300 after head node...\n");
	append(&head, &tail, 0, 2300);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Appending node with data of -2300 after tail node...\n");
	append(&head, &tail, listSizeHead(head) - 1, -2300);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Loading node 0 with data of 0...\n");
	loadNode(head, 0, 0);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Loading tail node with data of 255...\n");
	loadNode(head, listSizeHead(head) - 1, 255);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Deleting head node...\n");
	deleteNode(&head, &tail, 0);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Deleting tail node...\n");
	deleteNode(&head, &tail, listSizeHead(head) - 1);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	printf("Deleting node 2...\n");
	deleteNode(&head, &tail, 2);
	printf("Size of the list is: %d\n", listSizeHead(head));
	printIntDataHead(head);
	copyList(head, &copyHead, &copyTail);
	printf("Size of the list is: %d\n", listSizeHead(copyHead));
	printIntDataHead(copyHead);
	printf("The node location of 3 is %d\n", findData(copyHead, 3));
 
	destroyListHead(head);
	return 0;
}
 
void createList(node **headd, node **taill, int elements)
{
	int i;
	node *new, *head, *tail;
	new = head  = tail = NULL;
 
	for(i = 1; i<=elements; i++)
	{
		if (head == NULL)
		{
			head = (node *) malloc(sizeof(node));
			tail = head;
			head->prev = NULL;
			head->next = NULL;
		}
		else
		{
			new = (node *) malloc(sizeof(node));
			new->prev = tail;
			new->next = NULL;
			tail->next = new;
			tail = new;
		}
	}
	*headd = head;
	*taill = tail;
}
 
void destroyListHead(node *head)
{
	node *temp;
	node *temp2;
	temp = NULL;
	temp2 = NULL;
	temp = head;
	while(temp != NULL)
	{
		temp2 = temp->next;
		if (temp->prev != NULL) temp->prev = NULL;
		if (temp->next != NULL) temp->next = NULL;
		free(temp);
		temp = temp2;	
	}
}
 
void destroyListTail(node *tail)
{
	node *temp;
	node *temp2;
	temp = NULL;
	temp2 = NULL;
	temp = tail;
	while(temp != NULL)
	{
		temp2 = temp->prev;
		if (temp->prev != NULL) temp->prev = NULL;
		if (temp->next != NULL) temp->next = NULL;
		free(temp);
		temp = temp2;	
	}
}
 
int listSizeHead(node *head)
{
	int size = 0;
	while (head != NULL)
	{	
		head = head->next;
		size++;
	}
	return size;
}
 
int listSizeTail(node *tail)
{
        int size = 0;
        while (tail != NULL)
        {
                tail = tail->prev;
                size++;
        }
        return size;
}
 
void printIntDataHead(node * head)
{
	node * temp = NULL;
 
	temp = head;
	while(temp != NULL)
	{
		printf("%d ",temp->data);
		temp = temp->next;
	}
	printf("\n");
}
 
void insert(node ** head, node ** tail, int position, int data)
{
	int i;
	node *temp, *temp2;
	temp = temp2 = NULL;
 
	temp = *head;
	for(i = 0; i < position; i++)
	{
		temp = temp -> next;
	}
 
		if (*head == NULL)
		{
			*head = (node *) malloc(sizeof(node));
			*tail = *head;
			(*head)->prev = NULL;
			(*head)->next = NULL;
			(*head)->data = data;
		}
		else if (*head == temp)
		{
			temp2 = (node *) malloc (sizeof(node));
			temp2->next = *head;
			(*head)->prev = temp2;
			*head = (*head)->prev;
			(*head)->prev = NULL;
			(*head)->data = data;
		}
		else
		{
			temp2 = (node *) malloc (sizeof(node));	
			temp2->next = temp;
			temp2->prev = temp->prev;
			temp->prev->next = temp2;
			temp->prev = temp2;
			temp2->data = data;
		}
}
 
void append(node **head, node **tail, int position, int data)
{
	int i;
	node *temp, *temp2;
	temp = temp2 = NULL;
 
	temp = *head;
	for(i = 0; i < position; i++)
	{
		temp = temp -> next;
	}
 
		if (*head == NULL)
		{
			*head = (node *) malloc(sizeof(node));
			*tail = *head;
			(*head)->prev = NULL;
			(*head)->next = NULL;
			(*head)->data = data;
		}
		else if (*tail == temp)
		{
			temp2 = (node *) malloc (sizeof(node));
			temp2->prev = *tail;
			temp2->next = NULL;
			(*tail)->next = temp2;
			*tail = temp2;
			(*tail)->data = data;
		}
		else
		{
			temp2 = (node *) malloc (sizeof(node));
			temp2->prev = temp;
			temp2->next = temp->next;
			temp->next->prev = temp2;
			temp->next = temp2;
			temp2->data = data;
 
		}
 
}
 
void deleteNode(node **head, node **tail, int position)
{
	int i;
	node * temp = NULL;
 
	temp = *head;
	for(i = 0; i < position; i++)
	{
		temp = temp->next;
	}
	if(temp != *head && temp != *tail)
	{
		temp->next->prev = temp->prev;
		temp->prev->next = temp->next;
		temp->prev = NULL;
		temp->next = NULL;
	}
	else if (temp == *head)
	{
		temp->next->prev = NULL;
		*head = temp->next;
		temp->next = NULL;
	}
	else
	{
		temp->prev->next = NULL;
		*tail = temp->prev;
		temp->prev = NULL;
	}
	free(temp);
}
 
void loadListData(node *head)
{
	int i = 0;
	node *temp = NULL;
	temp = head;
	printf("Enter a value or -1 to quit: ");
	scanf("%d", &i);
	while(i != -1)
	{
		temp->data = i;
		temp = temp->next;
		if(temp == NULL)
		{
			printf("List is full of data!\n");
			break;
		}
		printf("Enter a value or -1 to quit: ");
		scanf("%d", &i);
	}
 
}
 
 
void loadNode(node *head, int position, int value)
{
	int i;
	node *temp = NULL;
	temp = head;
 
	temp = head;
	for(i = 0; i < position; i++)
	{
		temp = temp->next;
	}
	temp->data = value;
}
 
void createNode(node* head, node* tail)
{
	head = (node *) malloc(sizeof(node));
	tail = head;
	head->prev = NULL;
	head->next = NULL;
}
 
void copyList(node *head, node **copyHead, node **copyTail)
{
	node *new, *temp;
	new = *copyHead = *copyTail = temp = NULL;
	temp = head;
	while(temp != NULL)
	{
		if (*copyHead == NULL)
		{
			*copyHead = (node *) malloc(sizeof(node));
			*copyTail = *copyHead;
			(*copyHead)->prev = NULL;
			(*copyHead)->next = NULL;
			(*copyHead)->data = temp->data;
		}
		else
		{
			new = (node *) malloc(sizeof(node));
			new->prev = *copyTail;
			new->next = NULL;
			(*copyTail)->next = new;
			*copyTail = new;
			(*copyTail)->data = temp->data;
		}
		temp = temp->next;
	}
}
 
int findData(node *head, int data)
{
	int counter = 0;
	while(head != NULL)
	{
		if(head->data == data) break;
		counter++;
		head = head->next;
	}
	return counter;
}


lab46:~/src/data$ ./linkedListDev
Creating a list of 4 nodes...
Size of the list is: 4
Load list data
Enter a value or -1 to quit: 1
Enter a value or -1 to quit: 2
Enter a value or -1 to quit: 3
Enter a value or -1 to quit: 4
List is full of data!
1 2 3 4
Inserting node 0 with data of 3200 before head node...
Size of the list is: 5
3200 1 2 3 4
Inserting node with data of -3200 before tail node...
Size of the list is: 6
3200 1 2 3 -3200 4
Appending node with data of 2300 after head node...
Size of the list is: 7
3200 2300 1 2 3 -3200 4
Appending node with data of -2300 after tail node...
Size of the list is: 8
3200 2300 1 2 3 -3200 4 -2300
Loading node 0 with data of 0...
Size of the list is: 8
0 2300 1 2 3 -3200 4 -2300
Loading tail node with data of 255...
Size of the list is: 8
0 2300 1 2 3 -3200 4 255
Deleting head node...
Size of the list is: 7
2300 1 2 3 -3200 4 255
Deleting tail node...
Size of the list is: 6
2300 1 2 3 -3200 4
Deleting node 2...
Size of the list is: 5
2300 1 3 -3200 4
Size of the list is: 5
2300 1 3 -3200 4
The node location of 3 is 2
lab46:~/src/data$


References

Top

The element of the stack data structure which is available for stack operations (see the data structures topic “Stack” for details of stack operations) is known as the top of TOS (top of stack). The stack position top may have data “pushed” (see the data topic “Pushing” for details of the stack operation push) into it at which point the stack pointer, a pointer pointing to the stack element which is available for stack operations, is incremented so as to expose the next stack element for stack operations. The stack position top may also have data “popped” (see the data topic “Popping” for details of the stack operation pop) from it at which point the stack pointer, is decremented to expose the next stack element for stack operations.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/Stack_(abstract_data_type)”>http://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a></html>

Overflow Condition

If, a data structure such as a stack is full and cannot accept (store) anymore data, it is considered to be in an overflow state.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/Stack_(abstract_data_type)”>http://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a></html>

Underflow Condition

If, a data structure, such as a stack, is empty, no more data can be taken from it; it cannot be “popped” again as the data retreived would be erroneous, and the data structure position pointer, the stack pointer in the case of stacks, would be manipulated to point to some memory location which is no longer part of the data structure; this is considered to be the “underflow” state.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/Stack_(abstract_data_type)”>http://en.wikipedia.org/wiki/Stack_(abstract_data_type)</a></html>

Free

The function free, is used to release heap (see the data topic “Heap” for details) memory which was previously allocated dynamically, that is at run time, through the use of one of the memory allocation functions. free takes a single pointer argument; it releases the memory pointed to by its argument.

References

Structure

A structure or record is a collection of variables grouped together under a single identifier. The data are related somehow, that is the point of a structure or record. A classic example of a structure or record is that of an employee. Character array or string members of an employee structure or record might be the employee's first and last names, street, address, city, and state of residence. Integer members of the employee structure or record might be employee number, age, etc. The structure data type, also known as an abstract data type, provides an elegant and powerful way for keeping related data together.

References

Queue

A queue is a FIFO (see the data topic “FILO/FIFO” for details) type data structure. That is, data is taken from the queue in the same order that it was placed into it. Enqueuing Dequeue The following program demonstrates an array-based queue.

queueTest.c
//queueTest.c
//John T. Rine
//October 29, 2011
 
#include<stdio.h>
#include<stdlib.h>
 
struct Queue
{
	char *queueArray;
	int count;
	int size;
	int startIndex;
};
 
typedef  struct Queue queue;
 
 
void createQueue(queue *, int);
void destroyQueue(queue *);
void enqueue(queue *, char);
void printQueue(queue *);
int queueCount(queue *);
char dequeue(queue *);
 
int main(int argc, char **argv)
{
	queue newQueue;
 
	createQueue(&newQueue, 25);
	destroyQueue(&newQueue);
	enqueue(&newQueue, 'J');
        enqueue(&newQueue, 'o');
        enqueue(&newQueue, 'h');
        enqueue(&newQueue, 'n');
	printf("Calling printQueue(&newQueue)...\n");
        printQueue(&newQueue);
	printf("Calling and printing return value from dequeue...\n");
	printf("%c, ", dequeue(&newQueue));
        printf("%c, ", dequeue(&newQueue));
	printf("\n");
	printf("Calling printQueue(&newQueue)...\n");
	printQueue(&newQueue);
 
	return 0;
}
 
void createQueue(queue *queuePTR, int size)
{
	char *queueArrayPTR = NULL;
	queueArrayPTR = (char *)malloc(sizeof(char) * size);
	queuePTR->queueArray = queueArrayPTR;
	queuePTR->size = size;
	queuePTR->count = 0;
	queuePTR->startIndex = 0;
}
 
void destroyQueue(queue *queuePTR)
{
	free(queuePTR->queueArray);
}
 
void enqueue(queue *queuePTR, char data)
{
	int queueArrayIndex;
	if(queuePTR->count < queuePTR->size)
	{
		queueArrayIndex = queuePTR->startIndex + queuePTR->count;
		queuePTR->queueArray[queueArrayIndex] = data;
		queuePTR->count++;
	}
	else printf("Queue is full!\n");  
}
 
void printQueue(queue *queuePTR)
{
	int i;
	for(i = 0; i < queuePTR->count; i++) printf("%c, ",queuePTR->queueArray[(queuePTR->startIndex + i)%queuePTR->size]);
	printf("\n");
}
 
 
int queueCount(queue *queuePTR)
{
	return queuePTR->count;
}
 
char dequeue(queue *queuePTR)
{
	char ret;
	if(queuePTR->count == 0)
	{
		 printf("queue is empty!\n");
		exit(1);
	}
	ret = queuePTR->queueArray[queuePTR->startIndex];
    	queuePTR->count--;
    	queuePTR->startIndex = (queuePTR->startIndex + 1)%queuePTR->size;
    	return ret;
}


This is the output of the queueTest.c program:

lab46:~/src/data$ gcc queueTest.c -o queueTest
lab46:~/src/data$ ./queueTest
Calling printQueue(&newQueue)...
J, o, h, n,
Calling and printing return value from dequeue...
J, o,
Calling printQueue(&newQueue)...
h, n,
lab46:~/src/data$
References
  1. <html><a href=“http://en.wikipedia.org/wiki/Queue_(abstract_data_type)”>http://en.wikipedia.org/wiki/Queue_(abstract_data_type)</a></html>

Array

An array is a set of similar data type data stored in a contiguous section of memory. Since data contained in a array is packaged in similar sized memory blocks and stored in contiguous memory locations, it becomes possible to simply add an array element offset to the base address of the array to access data at a specific element withing the array. The following program illustrates the use off an index to access elements of an array.

arrayTest.c
//arrayTest.c
//John T. Rine
//October 29, 2011
 
#include<stdio.h>
 
int main(int argc, char **argv)
{
        char array[26] = {0};
        int i;
        printf("Enter a string (<= 25 character) to place into a character array\n");
        gets(array);
        printf("array contains %s\n", array);
        i = 0;
        while(array[i] != '\0')
        {
                printf("array[%d] = %c\n", i, array[i]);
                printf("*(array + %d) = %c\n", i, *(array + i));
                i++;
        }
 
        return 0;
}

This is the output of the arrayTest.c program listed above.

lab46:~/src/data$ ./arrayTest
Enter a string (<= 25 character) to place into a character array
John T. Rine
array contains John T. Rine
array[0] = J
*(array + 0) = J
array[1] = o
*(array + 1) = o
array[2] = h
*(array + 2) = h
array[3] = n
*(array + 3) = n
array[4] =
*(array + 4) =
array[5] = T
*(array + 5) = T
array[6] = .
*(array + 6) = .
array[7] =
*(array + 7) =
array[8] = R
*(array + 8) = R
array[9] = i
*(array + 9) = i
array[10] = n
*(array + 10) = n
array[11] = e
*(array + 11) = e
lab46:~/src/data$
References

LIFO/FIFO

LIFO is an acronym for “Last In, First Out”; FIFO is an acronym for “First In, First Out”. The stack is a last in, first out or LIFO data structure whereas the queue is a first in, first out or FIFO data structure. Due to the nature of the stack, one use is to reverse the order of data items. The data items to be reveresed are pushed onto the stack, and then to reverse them, they are popped off.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/LIFO_(computing)”>http://en.wikipedia.org/wiki/LIFO_(computing)</a></html>

hpc1 Topics

Keyword 1


References

Keyword 2

Identification and definition of the chosen keyword.

If you want to demonstrate something on the command-line, you can do so as follows:

lab46:~$ cd src
lab46:~/src$ gcc -o hello hello.c
lab46:~/src$ ./hello
Hello, World!
lab46:~/src$ 

Keyword 3

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:

/*
 * Sample code block
 */
#include <stdio.h>
 
int main()
{
    return(0);
}

Keyword 4

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you want to demonstrate something on the command-line, you can do so as follows:

lab46:~$ cd src
lab46:~/src$ gcc -o hello hello.c
lab46:~/src$ ./hello
Hello, World!
lab46:~/src$ 

Keyword 5

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:

/*
 * Sample code block
 */
#include <stdio.h>
 
int main()
{
    return(0);
}

Keyword 6

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you want to demonstrate something on the command-line, you can do so as follows:

lab46:~$ cd src
lab46:~/src$ gcc -o hello hello.c
lab46:~/src$ ./hello
Hello, World!
lab46:~/src$ 

Keyword 7

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:

/*
 * Sample code block
 */
#include <stdio.h>
 
int main()
{
    return(0);
}

Keyword 8

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you want to demonstrate something on the command-line, you can do so as follows:

lab46:~$ cd src
lab46:~/src$ gcc -o hello hello.c
lab46:~/src$ ./hello
Hello, World!
lab46:~/src$ 

Keyword 9

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:

/*
 * Sample code block
 */
#include <stdio.h>
 
int main()
{
    return(0);
}

Keyword 10

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you want to demonstrate something on the command-line, you can do so as follows:

lab46:~$ cd src
lab46:~/src$ gcc -o hello hello.c
lab46:~/src$ ./hello
Hello, World!
lab46:~/src$ 

Keyword 11

Identification and definition of the chosen keyword. Substitute “keyword” with the actual keyword.

If you wish to aid your definition with a code sample, you can do so by using a wiki code block, an example follows:

/*
 * Sample code block
 */
#include <stdio.h>
 
int main()
{
    return(0);
}

sysprog Topics

fork

The fork() system call takes no arguments and returns a process ID. fork() is used to create new processes which are child processes of the caller. Once a child process has been created both processes will execute the next instruction following the fork call. The returned PID value is the only way to distinguish between the child and the parent. If calling fork is successfully executed, Unix/Linux will make two identical copies of address spaces, one for the parent and the other for the child. Both processes will start their execution at the next statement following fork.
Regarding fork's return value, the man page says the following:

from man fork:
RETURN VALUE
On success, the PID of the child process is returned in the parent, and
0 is returned in the child.  On failure, -1 is returned in the  parent,
no child process is created, and errno is set appropriately.

The following code asks the user to enter the number of iterations that the parent and child processes should execute. Next, fork is called with fork assigning its return value of type pid_t to pid. Once fork is called, fork's return value is used to determine whether what is being printed currently is the child or the parent. If the return value is 0, then its the child, if its some positive value greater than 0, then its the parent.

forkExample.c
//forkExample.c
//John T. Rine
//October 23, 2011
 
#include <sys/types.h>
#include <stdlib.h>
#include<stdio.h>
 
#define CHILD 0
 
int globalTestVar = 0;
 
char *child(int *);
char *parent();
char *error();
 
 
 
int main(int argc, char **argv)
{
        char * procID = '\0';
        int localTestVar = 0;
        int *localTestVarPTR = NULL;
        localTestVarPTR = &localTestVar;
 
        pid_t pid;
 
        printf("Enter a global variable value\n");
        scanf("%d", &globalTestVar);
 
        printf("Enter a local variable value\n");
        scanf("%d", &localTestVar);
 
 
        pid = fork();
 
        //Error, failed to fork
        if (pid < CHILD) procID = error();
        //child
        else if (pid == CHILD) procID = child(localTestVarPTR);
        //parent
        else procID = parent();
 
        //Executed by both parent and child.
        printf("procID = %s\n", procID);
        printf("Global variable = %d\n", globalTestVar);
        printf("Local variable = %d\n", localTestVar);
 
}
 
char *child(int *localTestVarPtr)
{
        char *procID;
        procID = "Child Process: ";
        ++*localTestVarPtr;
        ++globalTestVar;
        return procID;
}
 
char *parent()
{
        char *procID;
        procID = "Parent Process:";
        return procID;
}
 
char *error()
{
        char *procID;
        procID = "Failed to fork";
        return procID;
}

Execution of forkExample.c

lab46:~/src/sysprog$ ./forkExample
Enter a global variable value
2
Enter a local variable value
3
procID = Parent Process:
Global variable = 2
Local variable = 3
procID = Child Process:
Global variable = 3
Local variable = 4
lab46:~/src/sysprog$
References
  1. Understanding Unix/Linux System Programming by Bruce Molay

Threads-part deux (instructor's permission)

The main comprises a single, default thread. All other threads must be explicitly created by the programmer. The function pthread_create creates a new thread and makes it executable. This routine can be called any number of times from anywhere within your code. The maximum number of threads that may be created by a process is implementation dependent. For example, the code below uses the number of arguments other than the file name (argc - 1) to create a given number of threads in the program.
There are many ways in which a thread may be terminated. The thread returns normally from its starting routine. It's work is done. The thread makes a call to the pthread_exit whether its work is done or not. The thread is canceled by another thread via the pthread_cancel routine. The entire process is terminated due to making a call to either the exec() or exit(). If main() finishes first, without calling pthread_exit explicitly itself.

The program below uses the following pthread library functions:

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg)


pthread_exit()

pthread_exit() enables the programmer to specify an optional termination status parameter. This optional parameter is typically returned to threads “joining” the terminated thread.
Regarding the calling of pthread_exit from main, there is a problem if main finishes before the threads it created if pthread_exit() isn't called explicitly. All of the threads it created will terminate because main is done and no longer exists to support the threads. By having main explicitly call pthread_exit as the last thing it does, main will kept alive to support the threads it created until they are done.


threadTest.c
//threadTest.c
//John T. Rine
//October 29, 2011
 
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
 
void *PrintMessage(void *message)
{
   printf("%s\n", message);
   pthread_exit(NULL);
}
 
int main(int argc, char **argv)
{
        if(argc == 1)
        {
                printf("No threads specified, exiting...\n");
                exit(1);
        }
        pthread_t threads[argc - 1];
        int rc, t;
        for(t=0;t<argc - 1;t++)
        {
                printf("In main: creating thread %ld\n", t);
                rc = pthread_create(&threads[t], NULL, PrintMessage, *(argv + t + 1));
                if (rc)
                {
                        printf("ERROR; return code from pthread_create() is %d\n", rc);
                        exit(-1);
                }
        }
        pthread_exit(NULL);
}


Compilation, linking, and execution of the code listed above:

lab46:~/src/sysprog$ gcc threadTest.c -o threadTest -lpthread
lab46:~/src/sysprog$ ./threadTest
No threads specified, exiting...
lab46:~/src/sysprog$ ./threadTest John
In main: creating thread 0
John
lab46:~/src/sysprog$ ./threadTest John Thomas
In main: creating thread 0
In main: creating thread 1
John
Thomas
lab46:~/src/sysprog$ ./threadTest John Thomas Rine
In main: creating thread 0
In main: creating thread 1
John
In main: creating thread 2
Thomas
Rine
lab46:~/src/sysprog$
References
  1. Understanding Unix/Linux System Programming-A Guide to Theory and Practice, Bruce Molay

POSIX

POSIX is an acronym for “Portable Operating System Interface for UniX”. POSIX is the name of a set of related standards specified by the IEEE to define the application programming interface (API), along with shell and utilities interfaces, for software compatible with variants of the Unix operating system, although the standard can apply to any operating system. POSIX support guarantees code is portable from system to system and it is increasingly becoming a requirement that applications conform to POSIX standards. For example, the USA's Joint Technical Architecture—Army (JTA-A) standards set specifies that conformance to the POSIX standard is critical to support software interoperability.

Wikipedia (http://en.wikipedia.org/wiki/POSIX) lists items addressed in the various versions of POSIX:
Parts before 1997, POSIX comprised several standards:

POSIX.1, Core Services (incorporates Standard ANSI C) (IEEE Std 1003.1-1988) 
  * Process Creation and Control
  * Signals
  * Floating Point Exceptions
  * Segmentation / Memory Violations
  * Illegal Instructions
  * Bus Errors
  * Timers
  * File and Directory Operations
  * Pipes
  * C Library (Standard C)
  * I/O Port Interface and Control
  * Process Triggers

POSIX.1b, Real-time extensions (IEEE Std 1003.1b-1993) 
  * Priority Scheduling
  * Real-Time Signals
  * Clocks and Timers
  * Semaphores
  * Message Passing
  * Shared Memory
  * Asynch and Synch I/O
  * Memory Locking Interface

POSIX.1c, Threads extensions (IEEE Std 1003.1c-1995) 
  * Thread Creation, Control, and Cleanup
  * Thread Scheduling
  * Thread Synchronization
  * Signal Handling

POSIX.2, Shell and Utilities (IEEE Std 1003.2-1992) 
  * Command Interpreter
  * Utility Programs

Versions after 1997, the Austin Group developed the POSIX revisions. The specifications are known under the name Single UNIX Specification, before they become a POSIX standard when formally approved by the ISO.

POSIX:2001 or IEEE Std 1003.1-2001 equates to the Single UNIX Specification version 3[5]

This standard consisted of:
  * the Base Definitions, Issue 6,
  * the System Interfaces and Headers, Issue 6,
  * the Commands and Utilities, Issue 6.

POSIX:2004 or IEEE Std 1003.1-2004 involved a minor update of POSIX:2001. It incorporated two technical corrigenda.[6] Its contents are available on the web.[7]

POSIX:2008
As of 2009[update] POSIX:2008 or IEEE Std 1003.1-2008 represents the current version.[8][9] A free online copy is available.[10]
This standard consists of:
  * the Base Definitions, Issue 7,
  * the System Interfaces and Headers, Issue 7,
  * the Commands and Utilities, Issue 7.
References

The semaphore is a synchronization method. A semaphore is a kernel variable that is accessible by all of the processes currently executing on the system. Processes use semaphores to coordinate access to shared system resources between them. A semaphore is a counter; when it is zero, the semaphore can block a thread’s execution using sem_wait until another thread increments the counter using sem_post. The following example code came from http://pages.cs.wisc.edu/~travitch/pthreads_primer.html This is the result of compiling, linking and then executing the example code listed above:

#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

#define THREADS 20

sem_t OKToBuyMilk;
int milkAvailable;

void* buyer(void *);

int main(int argc, char **argv)
{
	int i;
	pthread_t threads[THREADS];

	milkAvailable = 0;

	// Initialize the semaphore with a value of 1.
	// Note the second argument: passing zero denotes
	// that the semaphore is shared between threads (and
	// not processes).
	if(sem_init(&OKToBuyMilk, 0, 1))
	{
		printf("Could not initialize a semaphore\n");
		return -1;
	}

	for(i = 0; i < THREADS; ++i)
	{
		if(pthread_create(&threads[i], NULL, &buyer, NULL))
		{
			printf("Could not create thread %d\n", i);
			return -1;
		}
	}	

	for(i = 0; i < THREADS; ++i)
	{
		if(pthread_join(threads[i], NULL))
		{
			printf("Could not join thread %d\n", i);	
			return -1;
		}
	}

	sem_destroy(&OKToBuyMilk);

	// Make sure we don't have too much milk.
	printf("Total milk: %d\n", milkAvailable);

	return 0;
}

void* buyer(void *arg)
{
	// P()
	sem_wait(&OKToBuyMilk);
	if(!milkAvailable)
	{
		// Buy some milk
		++milkAvailable;
	}
	// V()
	sem_post(&OKToBuyMilk);

	return NULL;
}
lab46:~/src/sysprog$ gcc testSemaphore.c -o testSemaphore -lpthread
lab46:~/src/sysprog$ ./testSemaphore
Total milk: 1
lab46:~/src/sysprog$
References

Mutexes (Mutual Exclusion)

The mutex is a synchronization method. The word mutex means mutual exclusion (between threads in this usage) and is a combination of the two words as follows: MUTual EXclusion. A mutex is used cooperatively between threads to guarantee that only one of the threads is allowed to access shared memory or run certain application code at a time.

References

Barriers

The barrier is a synchronization method. A barrier for a set of threads or processes makes any thread or process stop at mutex and cannot continue until the remaining threads or processes reach this barrier.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/Barrier_(computer_science)”>http://en.wikipedia.org/wiki/Barrier_(computer_science)</a></html>

File Locks

File locking is a device that controls access to a file by allowing only one process to access it at one time.

References

Asynchronous Input

Asynchronous input, is a non-blocking type of I/O that allows other processing to continue while input is being received.

References

File Access

First, Linux utilizes permissions bits to control file access. There are three types of access: read, write, and execute. Also there is file locking which is a device that controls access to a file by allowing only one process to access it at one time.

References

System Calls

Kernel space is protected, nothing contained in it can be used in a program (called) directly. There are therefore services which are provided to act as interfaces between applications in user space and the kernel. A system call is the only way a programmer may use these services.

References

Bit Sets and Masks

Individual bits within a larger data package, a byte for instance, can be used to represent something. So rather than having a variable hold a value that represents only one thing, each bit within the variable can represent something. One example of the use of bit sets would be using chmod to set file permissions. Bit masks are used to manipulate only certain bits within a larger data package. Bit masking of data is carried out using two things, a bit mask, and a bitwise logical operation. Bit masks are used to either select or deselect which bits are set or changed; bitwise operations actually change the data based on the bit mask value. For example, data bits can be set using the bitwise or:

data = 00000000
mask = 01010101
data = data | bit mask
data = 01010101


Data bits can be reset using bitwise and:

data = 11111111
mask = 01010101
data = data & bit mask
data = 01010101


Other bitwise operations which can be used to bit mask and bit set repectively are exclusive or and complement.

References
  1. <html><a href=“http://en.wikipedia.org/wiki/Mask_(computing”>http://en.wikipedia.org/wiki/Mask_(computing)</a></html>

Signals

A signal is a software interrupt delivered to a process when an event occurs.
The code below was taken from http://www.c.happycodings.com/Gnu-Linux/code18.html and is used to demonstrate how signals work in a program.

//http://www.c.happycodings.com/Gnu-Linux/code18.html
//Signal, catch Ctrl-C

#include <stdio.h>
#include <unistd.h>  /* sleep(1) */
#include <signal.h>

void ex_program(int sig);

int main(void) {
 (void) signal(SIGINT, ex_program);

 while(1)
  printf("sleeping .. ZZZzzzz ....\n"), sleep(1);

 return 0;
}

void ex_program(int sig) {
 printf("Wake up call ... !!! - Catched signal: %d ... !!\n", sig);
 (void) signal(SIGINT, SIG_DFL);
}


Executing the code listed above produces the following output:

lab46:~/src/sysprog$ gcc sigTest.c -o sigTest
lab46:~/src/sysprog$ ./sigTest
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
^CWake up call ... !!! - Catched signal: 2 ... !!
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
sleeping .. ZZZzzzz ....
^C
lab46:~/src/sysprog$
References

data Objective

Objective-Data Structures in Applications

I would like to become more familiar with the various data structures, specific uses for each and be able to use them in applications.

Method

I will learn more about linked-lists, stacks, queues, graphs and trees by:


Measurement

Research and analysis of experimental results: see “Pushing” and “Popping” Part I Data Structures topics, also see “Overflow”, “Underflow”, “Linked list”, “Queues”, “malloc”, “free” Part II Data Structures topics for details.

Analysis

I have written linked list and stack libraries using linked nodes. I have also written array-based stacks and queues, each have dynamically-sized arrays all which compiled, linked, and executed successfully.led, linked and executed successfully.

hpc1 Objective

Objective

State the course objective; define what that objective entails.

Method

State the method you will use for measuring successful academic/intellectual achievement of this objective.

Measurement

Follow your method and obtain a measurement. Document the results here.

Analysis

Reflect upon your results of the measurement to ascertain your achievement of the particular course objective.

sysprog Objective

Objective-Parallel Computing

I would like to understand fork, what its purpose for being is and about spawning child processes in more detail. I would also like to understand mutltithreading, thread synchronization in more detail. I would like to understand more about parallel computing and how fork and multithreading play a part

Method

I will learn more about concurrency, fork, child processes, multithreading, and thread synchronization by:


Measurement

Research and analysis of experimental results: see “Threads”, ““Multithreading”, and “Semaphore” under Part I of the System programming topics, also see “Threads part deux”, “Semiphores” and “Mutexes” Part II Systeme programming topics for details.

Analysis

I wrote a simple mulithreaded application which compiled, linked and executed successfully. Regarding semaphores, I experimented with code which I found on the Internet. I was able, after modifying it, to compile, link and execute it. I worked with functions from both pthreads.h and semaphore.h.

Experiments

Experiment 1-String Literals and pointers to Dynamically Allocated Memory

Question

Is it possible to assign a string literal (using double-quotation marks), to a block of memory that has been dynamically allocated but has not had data yet assigned to it?

Resources

References

Hypothesis

Since it is possible to assign a string literal to a character pointer and then use it in a program (i.e.print out the data it points to), it should be possible to assign a string literal to pointer, pointing to a dynamically-allocated block of memory which hasn't yet been assigned data and then when the data is no longer needed, free it.
For example:

testStringLiteral.c
//testStringLiteral.c
//John T. Rine
//October 24, 2011
 
#include<stdio.h>
 
int main(int argc, char **argv)
{
        char * nameStringPTR = NULL;
 
        nameStringPTR = "John T. Rine";
        printf("nameStringPTR points to: %s\n:", nameStringPTR);
        return 0;
}

And the execution:

lab46:~/src/data$ gcc testStringLiteral.c -o testStringLiteral
lab46:~/src/data$ ./testStringLiteral
nameStringPTR points to: John T. Rine
lab46:~/src/data$

Experiment

This version of the testMalloc.c program corresponds to the first set of program output in the data section below.

useMalloc.c
//testMalloc.c
//John T. Rine
//October 24, 2011
 
#include<stdlib.h>
#include<stdio.h>
 
 
int main(int argc, char **argv)
{
 
        //malloc a char array
        char *arrayPTR = NULL;
        arrayPTR = malloc(sizeof(char) * 10);
        arrayPTR = "John Rine\0";
        printf("My name is: %s\n", arrayPTR);
 
        free(arrayPTR);
 
        return 0;
}

This version of the testMalloc.c program, with free commented out, corresponds to the second set of program output listed in the data section below.

testMalloc.c
//testMalloc.c
//John T. Rine
//October 24, 2011
 
#include<stdlib.h>
#include<stdio.h>
 
 
int main(int argc, char **argv)
{
 
        //malloc a char array
        char *arrayPTR = NULL;
        arrayPTR = malloc(sizeof(char) * 10);
        arrayPTR = "John Rine\0";
        printf("My name is: %s\n", arrayPTR);
 
        //free(arrayPTR);
 
        return 0;
}

This version of the testMalloc.c program, also with free commented out, corresponds to the third set of program output listed in the data section below. Note that printf function calls have been added to check the address contained in arrayPTR before and after assigning the string to the character pointer.

testMalloc.c
//testMalloc.c
//John T. Rine
//October 24, 2011
 
#include<stdlib.h>
#include<stdio.h>
 
 
int main(int argc, char **argv)
{
 
        //malloc a char array
        char *arrayPTR = NULL;
        arrayPTR = malloc(sizeof(char) * 10);
printf("The address contained in arrayPTR before assigning a string is: 0x%x\n", arrayPTR);
        arrayPTR = "John Rine\0";
printf("The address contained in arrayPTR before assigning a string is: 0x%x\n", arrayPTR);
        printf("My name is: %s\n", arrayPTR);
 
        //free(arrayPTR);
 
        return 0;
}

This last version of testMalloc.c assigns the individual characters in the string to the character-sized memory locations pointed to by the character pointer assigned to point to the dynamically allocated memory.

testMalloc.c
//testMalloc.c
//John T. Rine
//October 23, 2011
 
#include<stdlib.h>
#include<stdio.h>
 
 
int main(int argc, char **argv)
{
 
        //malloc a char array
        int i = 0;
        int ii = 0;
        char * inputString = "John T. Rine\0";
        char * string = NULL;
 
        printf("input string contains %s\n", inputString);
        while(*(inputString + i) != '\0') i++;
        printf("Character count = %d\n", i);
        string = (char *)malloc(sizeof(char) * (i + 1));
        for(ii = 0; ii <= (i + 1); ii++) *(string + ii) = *(inputString + ii);
        printf("Dynamically allocated array contains %s\n", string);
 
        free(string);
 
        return 0;
}

Data

Program output after assigning a string to a character pointer which points to a set of dynamically allocated character sized memory locations, printing out the contents pointed to, and then the freeing the memory. This output was created by the first version of the testMalloc.c program listed in the Experiment section listed above.

lab46:~/src/data$ gcc testMalloc.c -o testMalloc
lab46:~/src/data$ ./testMalloc
My name is: John Rine
*** glibc detected *** ./testMalloc: free(): invalid pointer: 0x00000000004006cc ***
======= Backtrace: =========
/lib/libc.so.6(+0x71ad6)[0x7f9874d51ad6]
/lib/libc.so.6(cfree+0x6c)[0x7f9874d5684c]
./testMalloc[0x4005d6]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f9874cfec4d]
./testMalloc[0x4004c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 00:11 2147645911                         /home/jr018429/src/data/testMalloc
00600000-00601000 rw-p 00000000 00:11 2147645911                         /home/jr018429/src/data/testMalloc
01f1e000-01f3f000 rw-p 00000000 00:00 0                                  [heap]
7f9870000000-7f9870021000 rw-p 00000000 00:00 0
7f9870021000-7f9874000000 ---p 00000000 00:00 0
7f9874aca000-7f9874ae0000 r-xp 00000000 ca:01 57346                      /lib/libgcc_s.so.1
7f9874ae0000-7f9874cdf000 ---p 00016000 ca:01 57346                      /lib/libgcc_s.so.1
7f9874cdf000-7f9874ce0000 rw-p 00015000 ca:01 57346                      /lib/libgcc_s.so.1
7f9874ce0000-7f9874e38000 r-xp 00000000 ca:01 57396                      /lib/libc-2.11.2.so
7f9874e38000-7f9875037000 ---p 00158000 ca:01 57396                      /lib/libc-2.11.2.so
7f9875037000-7f987503b000 r--p 00157000 ca:01 57396                      /lib/libc-2.11.2.so
7f987503b000-7f987503c000 rw-p 0015b000 ca:01 57396                      /lib/libc-2.11.2.so
7f987503c000-7f9875041000 rw-p 00000000 00:00 0
7f9875041000-7f987505f000 r-xp 00000000 ca:01 57564                      /lib/ld-2.11.2.so
7f987524c000-7f987524f000 rw-p 00000000 00:00 0
7f987525b000-7f987525e000 rw-p 00000000 00:00 0
7f987525e000-7f987525f000 r--p 0001d000 ca:01 57564                      /lib/ld-2.11.2.so
7f987525f000-7f9875260000 rw-p 0001e000 ca:01 57564                      /lib/ld-2.11.2.so
7f9875260000-7f9875261000 rw-p 00000000 00:00 0
7fffca6cc000-7fffca6e1000 rw-p 00000000 00:00 0                          [stack]
7fffca6f3000-7fffca6f4000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted
lab46:~/src/data$

Program output with free commented out. This output was created by the second version of the testMalloc.c program listed in the experiment section above.

lab46:~/src/data$ ./testMalloc
My name is: John Rine
lab46:~/src/data$

Program output with free commented out and with printf function calls to print out the address contained in arrayPTR before and after assigning the string to the character pointer. This program output was created by the third version of the testMalloc program listed in the experiment section above.

lab46:~/src/data$ gcc testMalloc.c -o testMalloc
lab46:~/src/data$ ./testMalloc
The address contained in arrayPTR before assigning a string is: 0x86d010
The address contained in arrayPTR before assigning a string is: 0x4006f6
My name is: John Rine
lab46:~/src/data$

This last set of program output corresponds the the last incarnation of the testMalloc.c program listed above in the experiment section.

lab46:~/src/data$ gcc testMalloc.c -o testMalloc
lab46:~/src/data$ ./testMalloc
input string contains John T. Rine
Character count = 12
Dynamically allocated array contains John T. Rine
lab46:~/src/data$

Analysis

Based on the data collected, my hypothesis was proven to not be correct. The first verision of the testMalloc.c program crashed when free executed which seemed to indicate that the issue seemed to be misuse of the free function. The second version of the program, in which free was commented out, ran flawlessly reinforcing the notion that the issue has to do with free. The third version of the program introduced printf calls to print out the address of arrayPTR before and after the assignment of the string literal to it. This version of the program demonstrates that assigning a string literal to a pointer pointing to newly allocated and not yet used memory causes the address stored in the pointer to no longer point to the dynamically llocated memory, but to the beginning address of the string literal. Therefore, when free attempted to free memory no longer being pointed to, it caused an exception to be thrown. The fourth and final version of the testMalloc.c program demonstrates that the proper way to assign a string to dynamically allocated memory in C is to do it character by character.

Conclusions

In C, even though it is possible to assign a string literal to a pointer and then use it, it is not possible to assign a string literal directly to a pointer pointing to dynamically allocated memory. This is because assigning a string literal to it changes the address stored in it so that when the memory is later freed, an exception is thrown because the pointer no longer points to the dynamically allocated memory.

Experiment 2-Curses Library, Function (F) Keys, and Terminal and Keyboard Settings

Question

Is it possible to use curses library input functions to handle and/or get function (F) keys in the same way that other key characters are handledretrieved?

Resources

Currently, for my system programming projects, I am developing a GUI (Graphical User Interface) interface, with which to program and display the results of operations (register values), for the 8085 CPU project begun in Computer Organization last sememster.
The GUI is to be developed using curses. I started with a function to read keyboardin input, however, the curses input function, getch, could not recognize the function (F) keys for some reason.

Date: Sun, 18 Sep 2011 21:25:29 -0400 (EDT)
From: John Rine <jr018429@lab46.corning-cc.edu>
Reply-To: "\\\"Systems\\\" Classes Discussion List" <sys@lab46.corning-cc.edu>
To: sys@lab46.corning-cc.edu
Subject: [SYS] Trouble with Curses recognizing F keys and other keyboard keys

All,
I am having trouble with curses recognizing function keys and the escape key.
I am using code like this:
#include<curses.h>

int main()
{
    int c;
    initscr();
    keypad(stdscr,TRUE);
    noecho();
    move(0,0);
    c=getch();
    while(c != KEY_F(1) && c != 'q')
    {
        move(0,0);
        printw("%c\n",c);
        refresh();
        c=getch();
    }
    endwin();
    return 0;
}
it will exit with 'q' but not KEY_F(1) or the F1 key. Also, the esc key is not recognized when using the KEY_EXIT constant. Anyone have any ideas as to how to get
function keys and the escape key to work with curses?

thanks,

John T. Rine

---
 Lab46: Penguin Powered


The instructor stated that he didn't have experience with curses and functions keys, but that this question could be the basis for an experiment; he challenged me to, using the scientific method, put together a hypothesis and a set of experiments whose outcome would help me answer the question posed.

Date: Mon, 19 Sep 2011 08:43:07 -0400
From: Matthew Haas <wedge@lab46.corning-cc.edu>
Reply-To: "\\\"Systems\\\" Classes Discussion List" <sys@lab46.corning-cc.edu>
To: sys@lab46.corning-cc.edu
Subject: Re: [SYS] Trouble with Curses recognizing F keys and other keyboard keys

On 09/18/2011 09:25 PM, John Rine wrote:
>
> I am having trouble with curses recognizing function keys and the escape key.
> I am using code like this:
> #include<curses.h>
>
> int main()
> {
>     int c;
>     initscr();
>     keypad(stdscr,TRUE);
>     noecho();
>     move(0,0);
>     c=getch();
>     while(c != KEY_F(1) && c != 'q')
>     {
>         move(0,0);
>         printw("%c\n",c);
>         refresh();
>         c=getch();
>     }
>     endwin();
>     return 0;
> }
> it will exit with 'q' but not KEY_F(1) or the F1 key. Also, the esc key is not recognized when using the KEY_EXIT constant. Anyone have any ideas as to how to get
> function keys and the escape key to work with curses?

I've never played with the function keys... so that would take some experimenting.
Escape, even though there may not be a #define for it (all the keys available to you are #define'd in /usr/include/curses.h, check it out), has a value.
The trick is, what is it? Hmm... this could be another experiment.
If you know that pretty much every key on the keyboard has a value (which ones do not have a direct value?), how could we figure out what the values of keys are?
What is the data type of the 'c' variable in the program above?
What type of data are we displaying in the printw() function call above?
Could you perhaps CHANGE the format specifier to match the actual data type of the 'c' variable? What would happen then?
If you then compile and run the program and start pressing keys, what happens? What do you see when you press 'a', 'A', spacebar? Do you know what these values
correspond to?
What do you think happens when you start pressing some keys that do not directly have printable characters associated with them, like... escape. What does it
display?

-Matthew
--
 Matthew Haas
 Lab46 System Administrator
 Instructor of Computer&  Information Science
 http://lab46.corning-cc.edu/haas/home/

_______________________________________________
SYS mailing list
SYS@lab46.corning-cc.edu
http://lab46.corning-cc.edu/mailman/listinfo/sys


References

Hypothesis

Based on what I've read, it should be possible to uses curses library functions to handle function key input.

Experiment

Since I was having trouble getting curses functions to recognize function (F) keys, I designed a simple program to read keyboard input using a curses function and then printed out the results. The program has the minium required to read and verify keyboard input.

//curseskeys.c
//John T. Rine
//October 29, 2011

#include <ncurses.h>

int main()
{       int ch;

        initscr();
        raw();
        keypad(stdscr, TRUE);
        noecho();

        printw("Type any character\n");
        ch = getch();
        if(ch == KEY_F(1))
                printw("F1 Key pressed");
         else
        {       printw("The pressed key is ");
                printw("%c", ch);
        }
        refresh(); 
        getch();
        endwin();
        return 0;
}


Since the F keys were not being recognized by the curses getch function, I wrote a program that gets keyboard input from stdin and stores it in an array. I then print out the characters stored in the array.

//getFkeys.c
//John T. Rine
//October 29, 2011

#include<stdio.h>

int main(int argc, char **argv)
{
        char array[10] = { 0 };
        int i;
        char c;
        fgets(array,9,stdin);
        for (i = 0; i < 10; i++) printf("Array[%d] = %d\n", i, array[i]);

        return 0;
}


Data

curseskeys.c execution with puTTY keyboard function and keyboard keys set to ESC[n~.

Result of entering the character 'a':

Type any character
The pressed key is a


Result of entering the F1 key:

lab46:~/src/sysprog$ ./curseskeys
lab46:~/src/sysprog$ ~



curseskeys.c execution with puTTY keyboard function and keyboard keys set to VT100+.

Result of entering the 'a' key:

Type any character
The pressed key is a


Result of entering the F1 key:

Type any character
F1 Key pressed



getFkeys.c execution with puTTY keyboard function and keyboard keys set to ESC[n~.

Result of entering the character 'a':

lab46:~/src/sysprog$ ./getFkeys
a
Array[0] = 97
Array[1] = 10
Array[2] = 0
Array[3] = 0
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0


Result of entering the F1 key:

lab46:~/src/sysprog$ ./getFkeys
^[[11~
Array[0] = 27
Array[1] = 91
Array[2] = 49
Array[3] = 49
Array[4] = 126
Array[5] = 10
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0
lab46:~/src/sysprog$


getFkeys.c execution with puTTY keyboard function and keyboard keys set to VT100+.

Result of entering the character 'a':

lab46:~/src/sysprog$ ./getFkeys
a
Array[0] = 97
Array[1] = 10
Array[2] = 0
Array[3] = 0
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0
lab46:~/src/sysprog$


Result of entering the F1 key:

lab46:~/src/sysprog$ ./getFkeys
^[OP
Array[0] = 27
Array[1] = 79
Array[2] = 80
Array[3] = 10
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0
lab46:~/src/sysprog$


Analysis

The data (program output from curseskeys.c) indicates that in order to use the curses getch function to get function (F) key input, the keyboard setting in puTTY must be set to something other than ESC[n~. The program executions that were able to read function (F) key input in this experiment were performed with the keyboad setting st to VT100+. The data collected from the the program output of getFkeys.c indicates that the keyboard/terminal settings do infact influence what is returned from a function (F) key keypress. With the puTTY keyboard/function key setting set to ESC[n~, the output of getFkeys.c with a character input of 'a' is:

a
Array[0] = 97
Array[1] = 10
Array[2] = 0
Array[3] = 0
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0


whereas the output with the puTTY keyboard/function key setting set as above, the output of getFkeys.c with a keyboard input of F1 is:

^[[11~
Array[0] = 27
Array[1] = 91
Array[2] = 49
Array[3] = 49
Array[4] = 126
Array[5] = 10
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0



With the puTTY keyboard/function key setting set to VT100+, the output of getFkeys.c with a character input of 'a' is:

a
Array[0] = 97
Array[1] = 10
Array[2] = 0
Array[3] = 0
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0


whereas the output with the puTTY keyboard/function key setting set as above, the output of getFkeys.c with a keyboard input of F1 is:

^[OP
Array[0] = 27
Array[1] = 79
Array[2] = 80
Array[3] = 10
Array[4] = 0
Array[5] = 0
Array[6] = 0
Array[7] = 0
Array[8] = 0
Array[9] = 0

indicating that the keyboard/terminal settings do NOT influence what is returned when a character key is pressed, but do influence what is returned when a function (F) key is pressed.

Conclusions

Since it appears that the terminal keyboard/function key setting does influence what is returned when a function (F) key is pressed, it would be a good idea to guarantee termminal settings before an applications, using function keys, executes. This could, or should be able to be accomplished either through the use of a shell script, modifying a system configuration file, or through the use of a programming library.

Experiment 3-Header Files, Compiling, and Linking

Question

If the library header file for functions used in a program is included in a source file, shouldn't compiling the source file alone cause the creation of an executable (that is linking is automatic, after all, the header file for the library was included in the source file)?

Resources

References

Hypothesis

Based on what I've read it should not link successfuly because standard c libraries are located in libc.so, while the math library is located in libm.so. The standard c libraries are linked by default, whereas the math library is not.

Experiment

I used the following program to collect data for the experiment. This file has math.h and stdio.h headers file included in the source file.

//mathTest.c
///John T. Rine
//October 30, 2011

#include <math.h>
#include <stdio.h>

int main (int argc, char **argv)
{
        double x = 0;
        printf("Enter a value to takes its square root\n");
        scanf("%lf", &x);
        printf ("The square root of %lf is %lf\n", x, sqrt(x));
        return 0;
}

Data

These are the results of the first attempt at compiling mathTest.c; the exact invocation of the gcc compiler uses was: gcc mathTest.c -o mathTest

lab46:~/src/sysprog$ gcc mathTest.c -o mathTest
/tmp/ccJHwf08.o: In function `main':
mathTest.c:(.text+0x51): undefined reference to `sqrt'
collect2: ld returned 1 exit status
lab46:~/src/sysprog$


These are the results of the second attempt at compiling mathTest.c; the exact invocation of the gcc compiler used was: gcc mathTest.c -o mathTest -lm

lab46:~/src/sysprog$ gcc mathTest.c -o mathTest -lm
lab46:~/src/sysprog$


This are the results of executing the program after successfully compiling and linking it.

lab46:~/src/sysprog$ ./mathTest
Enter a value to takes its square root
144
The square root of 144.000000 is 12.000000
lab46:~/src/sysprog$

Analysis

My hypothesis was correct as can be seen from the data collected from the experiment. If the math library is not linked, no executable is created, however, if the math library is linked, them the executable is created successfully.

Conclusions

If a library is not part of the C standard library, when the program is being compiled and linked there must be something to indicate what should be linked.
Since curses is not part of the C standard library, what happened while compiling and linking the math library will also occur when a curses program is compiled and linked.
For example compiling and linking a curses program without indicating what should be linked:

lab46:~/src/sysprog$ gcc curseskeys.c -o curseskeys
/tmp/cco3mJn0.o: In function `main':
curseskeys.c:(.text+0x9): undefined reference to `initscr'
curseskeys.c:(.text+0xe): undefined reference to `raw'
curseskeys.c:(.text+0x15): undefined reference to `stdscr'
curseskeys.c:(.text+0x22): undefined reference to `keypad'
curseskeys.c:(.text+0x27): undefined reference to `noecho'
curseskeys.c:(.text+0x36): undefined reference to `printw'
curseskeys.c:(.text+0x3d): undefined reference to `stdscr'
curseskeys.c:(.text+0x45): undefined reference to `wgetch'
curseskeys.c:(.text+0x60): undefined reference to `printw'
curseskeys.c:(.text+0x71): undefined reference to `printw'
curseskeys.c:(.text+0x85): undefined reference to `printw'
curseskeys.c:(.text+0x8c): undefined reference to `stdscr'
curseskeys.c:(.text+0x94): undefined reference to `wrefresh'
curseskeys.c:(.text+0x9b): undefined reference to `stdscr'
curseskeys.c:(.text+0xa3): undefined reference to `wgetch'
curseskeys.c:(.text+0xa8): undefined reference to `endwin'
collect2: ld returned 1 exit status
lab46:~/src/sysprog$

Compiling and linking a curses program with an indication of what should be linked:

lab46:~/src/sysprog$ gcc curseskeys.c -o curseskeys -lcurses
lab46:~/src/sysprog$


It is an interesting observation that the math library is linked as -lm and its dynamic library file name is libm.so. The curses library is linked as -lcurses; this implies that the curses dynamic library file name should be libcurses.so. Since the math library is included in a source file as #include<math.h>, and since the curses library is included in a source file as #include<curses.h>, then these dynamic libraries should be in the same path and also be in the same path as the c standard library (libc.so). A search for libcurses.so, therefore, int the c library path should be successful; there should be a dynamic library file by the name of libcurses.so in the c library path.