The task was to create simulation of warehouse's work. Producers (in an amount of argv[2]) create random number of "goods" (totally argv[1]), and consumers (in an amount of argv[3]) get random number of these goods. The full code is below.
I got segmentation error and tried to debug it and got the following:
Program received signal SIGSEGV, Segmentation fault.
__new_sem_init (sem=0x37, pshared=0, value=1) at sem_init.c:44
44 sem_init.c: No such file or directory
I think the problem is in address-of operator here
sem_init(&(shared->mutex), 0, 1);
How should I change the code to make it work?
Thanks a lot!
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#define NBUFF 10
#define MAXNTHREADS 100
#define min( a, b ) ( ( a < b) ? a : b )
int nitems, nproducers, nconsumers;
typedef struct shared_s
{
int buff[NBUFF];
int nput;
int nputval;
int nget;
int ngetval;
sem_t mutex, nempty, nstored;
} sharedtype;
int main(int argc, char **argv)
{
sharedtype * shared;
key_t key;
int shmid, semid;
int i, j, prodcount[MAXNTHREADS], conscount[MAXNTHREADS];
shared = mmap(NULL, sizeof(sharedtype),
PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);
/* Wrong argv */
if (argc != 4)
{
printf("usage: newconsumer <#items> <#producers> <#consumers>\n");
exit(1);
}
nitems = atoi(argv[1]);
nproducers = min(atoi(argv[2]), MAXNTHREADS);
nconsumers = min(atoi(argv[3]), MAXNTHREADS);
pid_t chpidpr [nproducers];
pid_t chpidcon [nconsumers];
/* initilising semaphores */
sem_init(&(shared->mutex), 0, 1);
sem_init(&(shared->nempty), 0, NBUFF);
sem_init(&(shared->nstored), 0, 0);
for (i = 0; i < nproducers; i++) {
prodcount[i] = 0;
switch (chpidpr[i] = fork())
{
case -1:
printf("fork error");
return 1;
case 0:
for (;;)
{
sem_wait(&shared->nempty);
sem_wait(&shared->mutex);
if (shared->nput >= nitems)
{
sem_post(&(shared->nstored));
sem_post(&(shared->nempty));
sem_post(&(shared->mutex));
return 0;
}
shared->buff[(shared->nput) %NBUFF] = shared->nputval;
(shared->nput)++;
(shared->nputval)++;
sem_post(&(shared->mutex));
sem_post(&(shared->nstored));
prodcount[i] += 1;
}
}
}
for (i = 0; i < nproducers; i++)
{
printf("producer count[%d] = %d\n", i, prodcount[i]);
}
for (i = 0; i < nconsumers; i++) {
conscount[i] = 0;
switch (chpidcon[i] = fork())
{
case -1:
printf("error");
return 1;
case 0:
for (;;)
{
sem_wait(&(shared->nstored));
sem_wait(&(shared->mutex));
if (shared->nget >= nitems)
{
sem_post(&(shared->nstored));
sem_post(&(shared->mutex));
return 0;
}
j = shared->nget % NBUFF;
if (shared->buff[j] != shared->ngetval)
{
printf("error: buff[%d] = %d\n", j, shared->buff[j]);
}
shared->nget++;
shared->ngetval++;
sem_post(&(shared->mutex));
sem_post(&(shared->nempty));
conscount[i] += 1;
}
}
}
for (i = 0; i < nconsumers; i++)
{
printf("consumer count[%d] = %d\n", i, conscount[i]);
}
/* destroying semaphores */
sem_destroy(&(shared->mutex));
sem_destroy(&(shared->nempty));
sem_destroy(&(shared->nstored));
exit(0);
}
It looks like your mmap call has failed and return -1. You aren't checking for this condition.
I did a quick addition, and it looks like mutex is at an offset of 56, or 0x38 from the base of sharedtype. Based on the crash report, sem = 0x37, which would be the address of shared->mutex if shared == -1.
I can't find any documentation on why one would call mmap with fd == -1, but I think this may be the source of the issue, combined with not validating the result.
Related
I was writing a simple shared memory test program like below.
And I used a line like below.
e_intf[i % 8].flag = i;
I thought it should be like below.
e_intf[i % 8]->flag = i;
But if I use "->" operator, I have errors.
This is a full source code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define SHM_KEY 0x9998
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t memory_update(void)
{
int32_t i = 0;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
while (1)
{
e_intf[i % 8].flag = i;
if (i < 8)
{
sprintf(e_intf[i % 8].name, "%s%d", "eth", (i % 8));
}
printf("memory_update : e_intf[%d].name = %s, e_intf[%d] = %d\n", i % 8, e_intf[i % 8].name, (i % 8), i);
sleep(2);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
return 0;
}
int32_t memory_read(void)
{
int32_t i;
int32_t shmid;
Ethernet_Interface_t *e_intf;
int32_t ret;
shmid = shmget(SHM_KEY, 8 * sizeof(Ethernet_Interface_t), 0644|IPC_CREAT);
if (shmid == -1)
{
perror("Shared Memory");
return -1;
}
e_intf = shmat(shmid, NULL, 0);
if (e_intf == (void *)-1)
{
perror("Shared Memory Attach");
return -1;
}
i = 0;
while (1)
{
printf("[%d]memory_read : index = %d\n", i, (i % 8));
printf("[%d]memory_read : e_intf[%d].name = %s\n", i, (i % 8), e_intf[i % 8].name);
printf("[%d]memory_read : e_intf[%d].flag = %d\n", i, (i % 8), e_intf[i % 8].flag);
if (e_intf[i % 8].flag == 42)
{
printf("[%d]memory_read : Exiting\n", i);
break;
}
sleep(1);
i++;
}
ret = shmdt(e_intf);
if (ret == -1)
{
perror("shmdt");
return -1;
}
ret = shmctl(shmid, IPC_RMID, 0);
if (ret == -1)
{
perror("shmctl");
return -1;
}
return 0;
}
int32_t main(int32_t argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid == 0)
{
/* child process */
memory_update();
}
else
{
/* parent process */
memory_read();
}
exit(0);
}
But when I made another simple test program for pointer operation.
I can use "->" operator as I expected.
Here is the source code for the test program for pointer operation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct _ethernet_interface {
char name[8];
int32_t flag;
} Ethernet_Interface_t;
int32_t main(int32_t argc, char *argv[])
{
Ethernet_Interface_t intf;
Ethernet_Interface_t *p_intf;
p_intf = malloc(sizeof(Ethernet_Interface_t));
intf.flag = 1111;
p_intf->flag = 2222;
printf("intf.flag = %d\n", intf.flag);
printf("p_intf->flag = %d\n", p_intf->flag);
return 0;
}
Can someone point out why I am confused with these 2 cases?
The answer is very simple - index dereferences the pointer:
pointer[n] === *(pointer + n)
so in your case:
e_intf[i % 8] === *(e_intf + i % 8)
and
e_intf[i % 8].flag == (*(e_intf + i % 8)).flag
if you want to use the -> operator you need pointer, not referenced object.
(&e_intf[i % 8]) -> flag
or
(e_intf + i % 8) -> flag
I am simulating F1 training. I am using fork() and shared memory between processes.
I am generating a random time for the cars that need to run for 5,400,000.
I fork() for each car.
the sons must simulate the generation of times.
the father takes care of the display, he also makes a system ("clear") with a sleep (1) to slow down the display.
but the program does not stop despite the 5,400,000 limit.
The program lasts more than 20min without stopping!
I would like it to generate the display a number of times and stop!
Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUMBER_OF_CARS 20
#define MIN 25000 // time generator
#define MAX 40000
int numeroVoiture[NUMBER_OF_CARS] = {44, 77, 11, 33, 3, 4, 5, 18, 14, 31, 16, 55, 10, 22, 7, 99, 9, 47, 6, 63};
typedef struct {
unsigned int id;
unsigned int s1;
unsigned int s2;
unsigned int s3;
unsigned int best_S1;
unsigned int best_S2;
unsigned int best_S3;
unsigned int tempsTotal;
unsigned int best_Circuit;
unsigned int lap;
unsigned int compteurStand;
unsigned int out;
} voiture;
voiture *shared_memory;
voiture copyTableau[NUMBER_OF_CARS];
int faireDesTours(int i);
unsigned int generateNumber(void);
void afficherTableau(void);
int compare (const void * a, const void * b);
void initVoiture(int i);
void sortLap(void);
int main(void)
{
/***************************************************
* Creating shared memory *
****************************************************/
int segment_id = shmget(IPC_PRIVATE, sizeof(voiture) * NUMBER_OF_CARS, 0666 | IPC_CREAT);
if (segment_id == -1) {
perror("shmget() failed !");
exit(EXIT_FAILURE);
}
shared_memory = shmat(segment_id, NULL, 0);
if (shared_memory == (void *) (-1)) {
perror("shmat() failed !");
exit(EXIT_FAILURE);
}
/**********************************************************
* Creation of child / cars *
**********************************************************/
for (int i = 0; i < NUMBER_OF_CARS; ++i)
{
/******** problem fork *********/
pid_t pid = fork();
if (pid == -1) {
perror("fork failed !");
exit(EXIT_FAILURE);
}
/******** child *********/
if(pid == 0) {
shared_memory[i].id = numeroVoiture[i]; //each car has a number
faireDesTours(i); //5400000
}
/******** father *********/
else {
wait(NULL);
system("clear");
// copy of array
memcpy( copyTableau, shared_memory, sizeof(copyTableau) );
//trier Tableau;
qsort( copyTableau, NUMBER_OF_CARS, sizeof(voiture), compare );
sortLap();
afficherTableau();
sleep(1);
}
}
/******** Detach memory segments *********/
shmdt(shared_memory);
/******** Delete shared memory *********/
shmctl(segment_id, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}
unsigned int tempsMaxCircuit = 5400000;
int faireDesTours( int i ) {
initVoiture(i);
unsigned int tour_complet;
while (shared_memory[i].tempsTotal <= tempsMaxCircuit) //no exceeded time
{
tour_complet = 0;
srand(time(NULL) + getpid());
/* **** S1 **** */
shared_memory[i].s1 = generateNumber();
if (shared_memory[i].s1 < shared_memory[i].best_S1) {
shared_memory[i].best_S1 = shared_memory[i].s1;
}
shared_memory[i].tempsTotal += shared_memory[i].s1;
tour_complet += shared_memory[i].s1;
/* *************************************** */
if (shared_memory[i].tempsTotal >= tempsMaxCircuit)
{
break;
}
/* **** S2 **** */
shared_memory[i].s2 = generateNumber();
if (shared_memory[i].s2 < shared_memory[i].best_S2) {
shared_memory[i].best_S2 = shared_memory[i].s2;
}
shared_memory[i].tempsTotal += shared_memory[i].s2;
tour_complet += shared_memory[i].s2;
/* *************************************** */
if (shared_memory[i].tempsTotal >= tempsMaxCircuit)
{
break;
}
/* **** S3 **** */
shared_memory[i].s3 = generateNumber();
if (shared_memory[i].s3 < shared_memory[i].best_S3) {
shared_memory[i].best_S3 = shared_memory[i].s3;
}
shared_memory[i].tempsTotal += shared_memory[i].s3;
tour_complet += shared_memory[i].s3;
/* *************************************** */
/* **** Best Time Circuit **** */
if (tour_complet < shared_memory[i].best_Circuit) {
shared_memory[i].best_Circuit = tour_complet;
shared_memory[i].best_Circuit = tour_complet;
}
/* *************************************** */
}
return 0;
}
unsigned int generateNumber(void)
{
return rand()%(MAX-MIN+1)+MIN;
}
void afficherTableau(void) { // Display
printf("\n\tBest times per complete lap\n");
printf(" ===================================================================================\n");
printf(" | ID | s1 | s2 | s3 | Tour | LAP |\n");
printf(" |==================================================================================\n");
for (int i = 0; i < NUMBER_OF_CARS; i++){
printf(" | %2d | %5d | %5d | %5d | %6d | %5d |\n", \
copyTableau[i].id, \
copyTableau[i].s1, copyTableau[i].s2, copyTableau[i].s3, \
copyTableau[i].best_Circuit,\
copyTableau[i].lap);
}
printf(" ===================================================================================\n\n");
}
// function sort
int compare(const void * a, const void * b)
{
voiture *voitureA = (voiture *)a;
voiture *voitureB = (voiture *)b;
return ( voitureA->best_Circuit - voitureB->best_Circuit );
}
// init each structure value of car
void initVoiture(int i) {
shared_memory[i].s1 = 0;
shared_memory[i].s2 = 0;
shared_memory[i].s3 = 0;
shared_memory[i].best_S1 = MAX;
shared_memory[i].best_S2 = MAX;
shared_memory[i].best_S3 = MAX;
shared_memory[i].best_Circuit = 3 * MAX;
shared_memory[i].tempsTotal = 0;
shared_memory[i].lap = 0;
shared_memory[i].compteurStand = 0;
shared_memory[i].out = false;
}
void sortLap(void) {
unsigned int difference;
for (int i = 1; i < NUMBER_OF_CARS; i++)
{
difference = ( copyTableau[i].best_Circuit - copyTableau[i - 1].best_Circuit );
copyTableau[i].lap = difference;
}
}
At the core, you have
for (int i = 0; i < NUMBER_OF_CARS; ++i)
{
/******** problem fork *********/
pid_t pid = fork();
if (pid == -1) {
perror("fork failed !");
exit(EXIT_FAILURE);
}
/******** child *********/
if(pid == 0) {
...
}
/******** father *********/
else {
wait(NULL);
...
}
}
You're missing a call to exit in the child. Without this, each child loops around and starts creating children of its own. It will eventually end, but not after creating a huge number of processes unintentionally.
By the way, it's kind of weird to create a child if the first thing the parent does is wait for the child to end.
For some reason I am getting a segmentation fault before any of my code is actually executed in the main() function. I have tried following the line of execution by putting in printfs but nothing is actually executed. I don't see anything in my program that would be causing a stack overflow, as I hardly even use memory.
If someone has better eyes than me and can spot this error it would be very much appreciated!
Main:
#include "../inc/protos.h"
HistogramData *histogram_data;
bool signal_caught = false;
sem_t *semaphore_id;
int letter_count[kLetterCount] = { 0 };
int wait_time = 0;
int main(void)
{
int shared_memory_id = 0;
key_t shared_memory_key = 0;
char buffer[kBufferLength] = { 0 };
int heads = 0;
int tails = 0;
printf("1");
histogram_data->signal_caught = false;
signal(SIGINT, signal_handler);
printf("2");
//Get the key to the allocated shared memory
shared_memory_key = ftok("/tmp", 'M');
if(shared_memory_key == -1)
{
printf("(CONSUMER) Cannot allocate key.\n");
return 1;
}
printf("3");
//Look for shared memory every 10 seconds until it finds it
while(true)
{
if((shared_memory_id = shmget(shared_memory_key, sizeof(histogram_data), 0)) == -1)
{
printf("4");
printf("(CONSUMER) Shared Memory does not exist. Please run the Producer program.\n");
sleep(kSleepTime);
}
else
{
printf("5");
break;
}
}
printf("(CONSUMER) Our Shared Memory ID is %d.\n", shared_memory_id);
//Attach the structure to the shared memory
histogram_data = (HistogramData*) shmat(shared_memory_id, NULL, 0);
if(histogram_data == NULL)
{
printf("(CONSUMER) Cannot attach to Shared Memory.\n");
return 3;
}
semaphore_id = sem_open("/HISTOGRAM_SEM", O_CREAT, S_IRUSR | S_IWUSR, 1);
signal(SIGALRM, alarm_handler);
//Set the watchdog timer to 2 seconds.
alarm(kAlarmSeconds);
//Detach from shared memory
shmdt(histogram_data);
return 0;
}
void signal_handler(int signal_number)
{
printf ("(CONSUMER) Received a signal. SIGINT ID is %d\n", signal_number);
histogram_data->signal_caught = true;
// Send SIGINT to Producer2
kill(histogram_data->producer2_pid, SIGINT);
// Send SIGINT to Producer1
kill(histogram_data->producer1_pid, SIGINT);
}
void print_line(int num)
{
int hundreds = num / 100;
num = num % 100;
int tens = num / 10;
num = num % 10;
int ones = num;
int i = 0;
for(i = 0; i < hundreds; i++)
{
printf("*");
}
for(i = 0; i < tens; i++)
{
printf("+");
}
for(i = 0; i < ones; i++)
{
printf("-");
}
printf("\n");
}
void display_histogram(int letter_count[])
{
int i = 0;
printf("\n********** HISTOGRAM **********\n");
for(i = 0; i < kLetterCount; i++)
{
printf("%c-%03d ", i + 65, letter_count[i]);
print_line(letter_count[i]);
}
}
void alarm_handler(int signal_number)
{
int wait_time = 0;
sem_wait(semaphore_id);
int i = 0;
for(i = 0; i < kDCReads; i++)
{
int* read_index = &histogram_data->read_index;
if(histogram_data->circular_buffer[*read_index] != 0)
{
int read_data = histogram_data->circular_buffer[*read_index];
histogram_data->circular_buffer[*read_index] = 0;
++letter_count[read_data - 65];
if(*read_index == kCircleBufferSize)
{
*read_index = 0;
}
if(*read_index == histogram_data->write_index)
{
break;
}
}
}
if(signal_caught == true)
{
//Read and write indexes from the histogram data structure
int* read_index = &histogram_data->read_index;
int* write_index = &histogram_data->write_index;
//Read data from buffer
while(*read_index != *write_index)
{
if(histogram_data->circular_buffer[*read_index])
{
//Data read in from the circular buffer
int read_data = histogram_data->circular_buffer[*read_index];
//Mark element as read
histogram_data->circular_buffer[*read_index] = 0;
++letter_count[read_data - 65];
//Increment the elements
(*read_index)++;
if(*read_index == 256)
{
*read_index = 0;
}
if(*read_index == *write_index)
{
break;
}
}
}
//Display a histogram listing
display_histogram(letter_count);
return;
}
wait_time++;
if(wait_time >= 5)
{
wait_time = 0;
display_histogram(letter_count);
}
//Release semaphore lock
sem_post(semaphore_id);
//Set the alarm for the watchdog to be two seconds
alarm(kAlarmSeconds);
//Reactivate watchdog signal
signal(signal_number, alarm_handler);
}
protos.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <signal.h>
#include <semaphore.h>
#define kCircleBufferSize 256
#define kBufferLength 126
#define kLetterCount 20
#define kDCReads 60
#define kAlarmSeconds 2
#define kSleepTime 10
typedef struct HistogramData HistogramData;
struct HistogramData
{
int read_index;
int write_index;
int is_wrap_around;
pid_t producer1_pid;
pid_t producer2_pid;
char circular_buffer[kCircleBufferSize];
bool signal_caught;
};
void signal_handler(int signal_number);
void print_line(int num);
void display_histogram(int letter_count[]);
void alarm_handler(int signal_number);
For some reason I am getting a segmentation fault before any of my code is actually executed in the main() function.
One of your preloaded data structures is likely to be causing overflow in the stack. You also have a lot of buffering going on to the output and, additionally, you have several places where you use printf() but do not append the newline \nto flush the console buffer. Alternatively, you can follow #sabbahillel's comment by putting fflush() after your printf() statements.
You create histogram_data as a pointer to HistogramData, but don't create a HistogramData object. Then, when you call histogram_data->signal_caught = false in main, you program dereferences a NULL pointer.
Instead, allocate memory for HistogramData before using the pointer (for example, histogram_data = malloc(sizeof *histogram_data);). Don't forget to free it later, too.
I am currently working on a producer-consumer implementation using C.
First, I create a buffer on the shared memory of a variable length that is given by the user in the consumer process.
Then, in the producer process, I need to access the shared memory and puts new data to the buffer so the consumer can consume.
Below is the consumer code:
#include "common.h"
#include <unistd.h>
int fd;
int errno;
int MY_LEN = 0;
Shared* shared_mem;
char *job[4];
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_CREAT | O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
ftruncate(fd, sizeof(Shared) + MY_LEN*sizeof(char *));
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared) + MY_LEN*sizeof(char *), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int init_shared_memory() {
shared_mem->data = 0;
int i;
for(i = 0; i < shared_mem->length; i++)
{
shared_mem->arr[i] = 0;
// shared_mem->arr[i] = (char *)calloc(1, sizeof(char*));
}
sem_init(&(shared_mem->mutex), 1, 1);
}
int init_job(){
int i;
for(i = 0; i < 4; i++)
{
job[i] = (char *)malloc(sizeof(char *));
}
}
int take_a_job(int index){
init_job();
char *ds = strdup(shared_mem->arr[index]);
job[0] = strtok(ds, "-");
int i = 1;
while(i < 4)
{
job[i] = strtok(NULL, "-");
i++;
}
// remove the job from the buffer
shared_mem->arr[index] = NULL;
}
int consume_job(int index){
printf("\nPrinter starts printing the job %s, %s pages from Buffer[%d]. The duration is %s seconds and the source is %s.\n",job[3], job[2], index, job[1], job[0]);
sleep(atoi(job[1])); // sleep for job[1] seconds.
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
init_shared_memory();
MY_LEN = atoi(argv[1]); // the first parameter following ./printer = the length of the buffer
shared_mem->length = MY_LEN;
//shared_mem->arr = (int*) &shared_mem->arr;
int index = 1;
*(shared_mem->arr) = "1-10-5-6";
*(shared_mem->arr + 1) = "2-5-2-7";
*(shared_mem->arr + 2) = "3-20-10-8";
*(shared_mem->arr + 3) = "4-7-4-9";
take_a_job(index);
int i;
for(i = 0; i < shared_mem->length; i++){
printf("\n\n%d set %s\n", i, shared_mem->arr[i]);
}
consume_job(index);
printf("\n\nHello second check\n\n");
while (1) {}
return 0;
}
Here is the producer code:
#include "common.h"
int fd;
Shared* shared_mem;
char *job;
int setup_shared_memory(){
fd = shm_open(MY_SHM, O_RDWR, 0666);
if(fd == -1){
printf("shm_open() failed\n");
exit(1);
}
}
int attach_shared_memory(){
shared_mem = (Shared*) mmap(NULL, sizeof(Shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
return 0;
}
int create_a_job(int args, char *argv[]){
int i;
job = (char *)calloc(8, sizeof(char *));
if(args != 5)
return 0; //the parameters are not correctly formatted
else{
for(i = 1; i < args; i++)
{
if(i > 1)
strcat(job, "-");
strcat(job, argv[i]);
}
}
strcat(job, "\0");
printf("\nthe job is %s\n", job);
}
int put_a_job(){
printf("shared_mem->length is %d\n\n", shared_mem->length);
int i;
for(i = 0; i < shared_mem->length; i++)
{
if(*(shared_mem->arr + i) == 0)
{
//shared_mem->arr[i] = (char *)malloc(sizeof(job));
//strcpy(shared_mem->arr[i], job);
*(shared_mem->arr + i) = (char *)job;
printf("\n\nThe index is %d\n", i);
//printf("\n\nthe argument is %s at %d\n", job, i);
return i;
}
}
printf("\n\nThe index is %d\n", i);
}
int main(int args, char *argv[]) {
setup_shared_memory();
attach_shared_memory();
// create a job with the parameters
int result = create_a_job(args, argv);
if(result == 0)
{
printf("Not the right parameters.\n");
printf("Plase enter client ID, job duration, number of pages and job ID.\n");
return 0;
}
int i;
put_a_job();
for (i=0; i < shared_mem->length; i++) {
printf("the argument is %s at %d\n", (char *)(shared_mem->arr + i), i);
}
printf("\n\n");
return 0;
}
The common.h file is
#ifndef _INCLUDE_COMMON_H_
#define _INCLUDE_COMMON_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// from `man shm_open`
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <string.h>
#include <semaphore.h>
#define MY_SHM "/JIT"
typedef struct {
sem_t mutex;
int data;
int length; // the length of the buffer
char *arr[0];
} Shared;
#endif //_INCLUDE_COMMON_H_
I first run ./consumer 10 & to allocate a buffer of length 10 and after, I run ./producer 1 2 3 4 to put the job to the buffer and print the buffer, I got garbage values
Any help would be really appreciated! Thank you!
Instruction
*(shared_mem->arr + i) = (char *)job;
is storing the pointer job into the shared mem, not the pointed value.
Maybe you want to use a strncpy.
You cannot share memory address between processes, because of Linux uses virtual memory. To make the story short an address in a process is not valid for a different process.
Be aware that you have a memory leakage because you never call free() for the allocated job.
For educational purposes, I wrote a program that forks a process and ...
the child continuously reads 3 files, prints the contents, sleeps for 10ms.
the parent keeps a counter for each file. each file also has a delay time associated with it.
each time a file's timer expires, the counter is incremented and the file is overwritten with the
new counter value. Each delay value is different, so all 3 files get updated at different rates.
The problem is, the counters only increment for a short time, and everything freezes after a few seconds. Can anyone give a good explanation of what is happening here?
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#define CHAN1WAIT 100000
#define CHAN2WAIT 750000
#define CHAN3WAIT 1000000
#define NCHAN 3
FILE *chanfiles[NCHAN] = {NULL, NULL, NULL}; //file pointers for fake 'devices'
char *filenames[NCHAN] = {"_chan1tmpfile_", "_chan2tmpfile_", "_chan3tmpfile_"};
int chanwait[NCHAN] = {CHAN1WAIT, CHAN2WAIT, CHAN3WAIT}; //time it takes for each 'device' to be updated with a new value
int chancount[NCHAN] = {0, 0, 0}; //value for each device
int clrcount = NCHAN * 8;
uint8_t chan1;
int read_chan (int chan)
{
char buf[4];
char c;
int i, ret;
short count = 0;
uint8_t set = 0;
char * retstr;
while (! set)
{
if (chanfiles[chan] == NULL) //if file is not in use
{
if ((chanfiles[chan] = fopen(filenames[chan], "r")) == NULL)
{
printf("Error opening file %s for reading.\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
while ((c = fgetc(chanfiles[chan])) != EOF)
{
buf[count] = c;
count++;
}
fclose(chanfiles[chan]);
chanfiles[chan] = NULL;
retstr = malloc(count + 1);
for (i = 0; i < count; i++) retstr[i] = buf[i];
ret = atoi(retstr);
free(retstr);
set = 1;
}
}
return ret;
}
void write_chan (int chan)
{
uint8_t set = 0;
while (! set)
{
if (chanfiles[chan] == NULL) //if file is not in use
{
if ((chanfiles[chan] = fopen(filenames[chan], "w")) == 0)
{
printf("Error opening file %s for writing.\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
if (fprintf(chanfiles[chan], "%d", chancount[chan]) < 0)
{
printf("Error writing to file %s:\n%s\n", filenames[chan], strerror(errno));
exit(-1);
}
fclose(chanfiles[chan]);
chanfiles[chan] = NULL;
set = 1;
}
}
}
time_t get_usecs()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec;
}
int main (int argc, char * argv[])
{
pid_t pid;
time_t curtime;
int i;
for (i = 0; i < NCHAN; i++) write_chan(i);
printf("\nChannel:");
for (i = 0; i < NCHAN; i++) printf("%8d", i);
printf("\n Value:");
pid = fork();
// This process reads all 3 files, prints the values,
// then sleeps for 10ms, in an infinite loop.
if (pid == 0)
{
int j;
while (1)
{
uint8_t set;
for (j = 0; j < NCHAN; j++)
{
int value;
set = 0;
value = read_chan(j);
printf("%8d", value);
}
fflush(stdout);
usleep(10000);
for (j = 0; j < clrcount; j++) printf("\b"); fflush(stdout);
}
}
// This process updates the values of all 3 files at
// different rates, based on the value in chanwait[]
// for each file.
else
{
time_t timers[NCHAN];
int i;
for (i = 0; i < NCHAN; i++) timers[i] = get_usecs();
while (1)
{
for (i = 0; i < NCHAN; i++)
{
if ((get_usecs() - timers[i]) >= chanwait[i])
{
chancount[i]++;
write_chan(i);
timers[i] = get_usecs();
}
}
}
}
}
I am not sure this is your only problem, but your get_usecs function is suspect. You probably meant this
return tv.tv_sec * 1000000 + tv.tv_usec;
Rather than
return tv.tv_sec + tv.tv_usec;
Although, note that time_t is only guaranteed to be large enough for the time in seconds, not the number of microseconds as you have used it.