I have been learning how to use Unix functions to program in C so that I can program Semaphore functionality by scratch (without pthreads), but I am currently stuck. The man pages told me to include particular header files to use functions of interest (such as malloc, tsleep, wakeup, etc.), but when I try to run my program with the headers and method calls, I receive the following errors:
/tmp//ccg29960.o: In function `allocate_semaphore':
/tmp//ccg29960.o(.text+0x28d): undefined reference to `simple_lock_init'
/tmp//ccg29960.o: In function `down_semaphore':
/tmp//ccg29960.o(.text+0x2fb): undefined reference to `tsleep'
/tmp//ccg29960.o: In function `up_semaphore':
/tmp//ccg29960.o(.text+0x3b5): undefined reference to `wakeup'
/tmp//ccg29960.o: In function `free_semaphore':
/tmp//ccg29960.o(.text+0x43b): undefined reference to `simple_lock'
/tmp//ccg29960.o(.text+0x4af): undefined reference to `simple_unlock'
collect2: ld returned 1 exit status
The relevant code is below:
//#include <stdio.h>
//#include <stdlib.h>
#include <sys/errno.h>
#include <sys/queue.h>
//#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/lock.h>
struct entry
{
pid_t id;
SIMPLEQ_ENTRY(entry) next;
} *np;
typedef struct
{
const char* name;
pid_t process;
pid_t p_process; //parent process
int count;
SIMPLEQ_HEAD(queuehead,entry) head;
struct simplelock *slock;
} named_semaphore;
named_semaphore* s_list[64];
int num_semaphores = 0;
int main()
{
//lockinit(0, 0, 0,0, 0);
printf("Hello world\n");
return 0;
}
//... irrelevant code elided
int allocate_semaphore( const char* name, int initial_count )
{
int num_elements, i;
named_semaphore *new_s;
//perform initial checks before creating a new semaphore
//make sure the given name is an acceptable length
num_elements = sizeof(name) / sizeof(*name);
if ( num_elements > 32 )
{
return ENAMETOOLONG;
}
//make sure the given name is unique to this process
for (i = 0; i < num_semaphores; i++)
{
if (s_list[i]->process == getpid() && strcmp(s_list[i]->name, name))
{
return EEXIST;
}
}
//make sure there are no more than 64 semaphores active
if (num_semaphores >= 64)
{
return ENOMEM;
}
//create a new semaphore and add it to the collection
new_s = (named_semaphore*) malloc(sizeof(named_semaphore), 0, 0);
new_s->name = name;
new_s->process = getpid();
new_s->p_process = getppid();
new_s->count = initial_count;
s_list[num_semaphores] = new_s;
++num_semaphores;
//initialize the waiting queue
SIMPLEQ_INIT( &(new_s->head) );
//initialize its lock
simple_lock_init( new_s->slock );
//need to handle negative initial_count somehow
return (0);
}
int down_semaphore( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if (s == NULL)
{
return (ENOENT);
}
s->count = (s->count) - 1;
if (s->count < 0)
{
//put process to sleep
tsleep(getpid(), getpriority(), 0, 0);
//add process to waiting queue
np = (struct entry *) malloc(sizeof(struct entry ));
np->id = getpid();
SIMPLEQ_INSERT_TAIL( &(s->head), np, next );
}
return 0;
}
int up_semaphore ( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if ( s == NULL )
{
return (ENOENT);
}
s->count = (s->count) + 1;
if (s->count <= 0)
{
//wakeup longest waiting process
wakeup( (SIMPLEQ_FIRST( &(s->head) ))->id );
//remove process from waiting queue
SIMPLEQ_REMOVE_HEAD( &(s->head), np, next );
free( np );
}
return 0;
}
int free_semaphore( const char* name )
{
named_semaphore* s;
s = getSemaphore( name );
if ( s == NULL )
{
return (ENOENT);
}
simple_lock( s->slock );
while ( (np = SIMPLEQ_FIRST( &(s->head) ) ) != NULL )
{
//wakeup the process and return ECONNABORTED
//wakeup( getSemaphore( np->id ) );
SIMPLEQ_REMOVE_HEAD( &(s->head), np, next );
free( np );
}
free( s );
simple_unlock( s->slock );
}
I am not done modifying/fixing the logic of my overall program (for example, the lock()ing only happens in 1/3 of the intended methods), but it would be wonderful to understand why I am getting my current error so that I know how to fix similar ones in the future.
To me it seems like the methods do not recognize their header files or that I am missing a required piece of information so that the two can communicate.
To fix the errors, I've tried rearranging and commenting out the listed header files and also renaming the method calls in uppercase letters like they were presented in the header file documentation.
Any help or insight is appreciated, and thank you in advance!
The man pages you read... those were section 9, weren't they? Section 9 is for kernel programming. You can't call those functions unless your code is in the kernel.