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.
Related
So i'm currently trying to code in unix using shared memory and the fork() function, I have an array of 10 structs and I would like to put that array into shared memory so that it can be accessed by a client program. I was hoping someone could point me in the right direction on how to do this.
the code I currently have is:
// Compiler Directives
// Standard Library Inclusions
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <time.h>
//Other Inclusions
struct strProcess
{
int nPriority;
int nPid;
};
// Function Prototypes (if not included within a header file)
int frand (int nInput);
int finval (int nInput);
void fsortasc(struct strProcess pArray[],int nInput);
// Main
int main(void)
{
// Variable Declarations
int nShmid,i,arraySize,nRpriority,j, nInput;
key_t nKey;
char *ptrshm, *ptrs;
int nSize;
pid_t pid;
struct strProcess pArray[10];
struct strProcess *Array;
Array = pArray;
// Code start
nKey = 5678;
FILE *f = fopen("logfile.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
printf("please enter the amount of processes to create for this cycle between 1 and 10 \n");
scanf("%d",&nInput);
if (nInput <= 0 || nInput > 10)
{
nInput = finval(nInput);
}
printf("%d", nInput);
nSize = sizeof(pArray) * 10;
//create segment
if ((nShmid = shmget(nKey,nSize, IPC_CREAT | 0666)) <0)
{
perror("shmget");
exit(1);
}
printf("segment created \n\n");
fprintf(f, "shared memory segment created");
Array *pArray = shmat(shmid,NULL, 0);
if (Array* pArray (-1))
{
perror("shmat");
exit(1);
}
printf("segment attached \n\n");
fprintf(f, "shared memory segment attached");
for(i = 0 ; i < nInput; i++)
{
if ((pid = fork()) < 0)
{
perror("fork");
exit(1);
}
if (pid == 0)
{
Array[i].nPid = getpid();
nRpriority = frand(nInput);
Array[i].nPriority = nRpriority;
printf("print job created with Pid %d and priority number %d",
getpid(), nRpriority);
fprintf(f, "print job created with Pid %d and priority number %d",
getpid(), nRpriority);
}
}
fprintf(f, " %d processes have been created", nInput);
fsortasc(pArray, nInput); /*sort array into ascending order by nRpriority values*/
// Function Definitions - in alphabetical order
int finval (int nInput)
{
while(nInput <= 0 || nInput > 10)
{
printf("please enter a number between 1 and 10 \n");
scanf("%d", &nInput);
}
return nInput;
}
int frand (int nInput)
{
int nRand;
nRand = (rand() % nInput)+1; /*set nRand == a random number
inbetween nInput and 1*/
return nRand; /*return the random number*/
}
void fsortasc(struct strProcess pArray[],int nInput)
{
struct strProcess temp; /*temporary storage for elements being swapped*/
int i, j;
for (i = 0; i < nInput - 1; i++)
{
for (j = 0; j < (nInput - 1-i); j++)
{
if (pArray[j].nPriority > pArray[j + 1].nPriority) /*if the current element is greater than the next element*/
{
temp = pArray[j];
pArray[j] = pArray[j + 1];
pArray[j + 1] = temp;
}
}
}
I have an array of 10 structs and I would like to put that array into shared memory ? It's very simple, first create array 10 struct variable and then create the shared memory using shmget of required size and then attach that shared memory with pointer and finally copy array of 10 structs into pointer attached with shmat. I added below simple code to understand your requirement.
typedef struct company {
int emp_id;
}cmp;
int main(int argc,char *argv[]) {
cmp cmp_info[10];
int shm_id, sze = sizeof(cmp_info) ,i;
/* I have an array of 10 structs -- with some data like emp_id*/
for(i=0 ;i<10 ;i++) {
printf("\n enter emp % Id \n",i);
scanf("%d",&cmp_info[i].emp_id);
}
/* create the shared memory of 'sze' size. */
shm_id = shmget(10,sze, IPC_CREAT | 0664);
perror("shmget");
/* attach the shared memory with shm_id */
cmp *shm_ptr = shmat(shm_id, NULL, 0);
perror("shmat");
/* I have an array of 10 structs and I would like to put that array into shared memory */
shm_ptr = cmp_info;//now shared memory contains array of 10 struct data
/** print using shm_ptr to verify **/
for(i=0;i<10;i++) {
printf("Employee[%d] Id is : [%d]\n",i,shm_ptr[i].emp_id);
}
/* once above things are done clients program can read from shared memory */
/** finaly de-atach the shared memory */
shmdt(shm_ptr);
}
Below snapshot is for your code, Explanation is in comments.
struct strProcess {
int nPriority;
int nPid;
};
int main(int argc,char *argv[]) {
// Variable Declarations
int nShmid,i,arraySize,nRpriority,j, nInput;
key_t nKey;
char *ptrshm, *ptrs;
int nSize;
struct strProcess pArray[10];//array of 10 structure
struct strProcess *Array;
//Array = pArray;
nKey = 5678;
FILE *f = fopen("logfile.txt", "w");
if(f == NULL) {
printf("Error opening file!\n");
exit(1);
}
nSize = sizeof(pArray);
//create segment
if((nShmid = shmget(nKey,nSize, IPC_CREAT | 0666)) < 0) {
perror("shmget");
exit(1);
}
else {
perror("shmget");
fprintf(f, "\n shared memory segment created\n");
}
Array = shmat(nShmid, NULL, 0);
perror("shmat");
/** loop to create exaCtly 10 process */
nInput = 10; /** call finval function **/
for(i = 0 ; i < nInput; i++) {
if(fork() == 0) {
srand(getpid());
Array[i].nPid = getpid();
nRpriority = rand()%10 + 1;//putting random no b/w 1 to 10..u can call your function also
Array[i].nPriority = nRpriority;
fprintf(f, "\nprint job created with Pid [%d] and priority number [%d]\n",
Array[i].nPid, Array[i].nPriority);
break;//must to avoid repeating
}
else {
;//parent does nothing
}
}
shmdt(Array);
//fprintf(f,"\n total [%d] processes have been created\n",nInput);
/* call fsortasc(pArray, nInput); */
fclose(f);
}
I hope it helps.
I have written this code which is supposed to make N producers (P) and a consumer (C). Those two exchange K messages which are in two separate shared memory segments (sms). P's send to C a line and their pid. C sends back this line capitalized with the pid of the P that sent it. When K messages have been sent C must calculate and print how many times P's have read their own message capitalized. I put a wait(NULL) in the end so that C waits for all P's to put their personal pid_match in a buffer of a 3rd sms so it can read the right values after. Instead when i execute the code it only reads the pid_match from the 1st P and then terminates. Why does that happen. I post the code below. If any examples of execution are usefull i can provide them.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "myheader.h"
int main (int argc , char* argv[]){
if(argc<3) {
printf("Programm needs more arguments (K and N) \n");
return(-1);
}
else
{
const int SHMSIZE = sizeof(struct message); // Shared Memory size = the size of a message
int K, N, k, n, child_pid, shmid_in, shmid_out, shmid_pid, full_in, empty_in, full_out, empty_out, empty_pid, full_pid, pid_match=0,status,G;
key_t shmkey_in, shmkey_out, semkey0_in, semkey1_in, semkey0_out, semkey1_out;
struct message *shm_in, *shm_out;
int *shm_pid;
//struct sembuf oparray[1]={0,1,0};
K=atoi(argv[1]);
N=atoi(argv[2]);
const int shm_pidsize = N*sizeof(int);
if(K==0 || N==0) return 0; //if no producers exist the programm should exit
printf("%d %d \n", K, N );
/* --- Keys Initialization --- */
shmkey_in = ftok("/OS1.c", 1);
shmkey_out = ftok("/OS1.c", 2);
semkey0_in = ftok("/OS1.c", 3); // full_in semkey
semkey1_in = ftok("/OS1.c", 4); // empty_in semkey Tou P oi 2 gia to sms in (apo P se C dld)
semkey0_out = ftok("/OS1.c", 5); // full_out semkey
semkey1_out = ftok("OS1.c", 6); // empty_out semkey Tou P oi 2 gia to sms out (apo C se P dld)
/* --- Shared memory creation --- */
shmid_in = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_out = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_pid = shmget(IPC_PRIVATE,shm_pidsize,IPC_CREAT | 0666); // shm_pid creation
shm_in = (struct message*)shmat(shmid_in,NULL,0);
shm_out = (struct message*)shmat(shmid_out,NULL,0);
shm_pid = (int*)shmat(shmid_pid,NULL,0); // shm_pid attach
/* --- Semaphore creation --- */
full_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
/* --- Semaphore Initialization --- */
union semum init0,init1;
init0.val=0;
init1.val=1;
semctl(full_in,0,SETVAL,init0); // full_in = 0
semctl(empty_in,0,SETVAL,init1); // empty_in = 1
semctl(full_out,0,SETVAL,init0); // full_out = 0
semctl(empty_out,0,SETVAL,init1); // emty_out = 1
semctl(full_pid,0,SETVAL,init0); // pid_full = 0
semctl(empty_pid,0,SETVAL,init1); // pid_empty = 1
/* --- Semaphore oparations buffers --- */
struct sembuf full_in_up = {0,1,0};
struct sembuf full_in_down = {0,-1,0};
struct sembuf empty_in_up = {0,1,0}; // Operations of P to semaphores 0,1,2
struct sembuf empty_in_down = {0,-1,0};
struct sembuf full_out_up = {0,1,0};
struct sembuf full_out_down = {0,-1,0};
struct sembuf empty_out_up = {0,1,0}; // Operations of C to semaphores 0,1,2
struct sembuf empty_out_down = {0,-1,0};
struct sembuf full_pid_up = {0,1,0};
struct sembuf full_pid_down = {0,-1,0};
struct sembuf empty_pid_up = {0,1,0};
struct sembuf empty_pid_down = {0,-1,0};
for(n=0; n<N; n++)
{
child_pid = fork();
//printf("child_pid = fork();\n ");
if (child_pid == 0)
{
printf(" --- this is %d th child with pid: %d---\n \n", n, getpid());
int pid_match = 0; // Initialize pid_match
while(1){
//printf("int pid_match = 0; // Initialize pid_match\n while(1){\n");
// printf("%d \n",semctl(empty_in,0,GETVAL));
// sleep(1);
semop(empty_in, &empty_in_down,1); // down(empty_in)
// printf("%d \n",semctl(empty_in,0,GETVAL));
//printf(" down(empty_in)\n");
struct message msg;
msg.pid = getpid();
char buf[max_line_length];
FILE *ptr_file;
ptr_file =fopen("input.txt","r");
if (!ptr_file) perror("File failed to open");
long curtime = time(NULL);
srand((unsigned int) curtime);
sleep(1); // produce & send
int i=1, j=0, luckyline = rand() % 5 + 1;
//printf("%d\n", luckyline);
while (fgets(buf, 1000, ptr_file)!=NULL && i<5)
{
if (i == luckyline)
{
//printf("%s \n",buf);
strcpy(msg.line,buf); // complete the message
strcpy(shm_in->line,msg.line); // send message to sms
shm_in->pid = getpid();
//printf("pid = %d\n",shm_in->pid );
break;
}
i++;
}
fclose(ptr_file);
// strcpy(shm_in->line, "message");
// printf("message copy\n");
// shm_in->pid = child_pid;
semop(full_in,&full_in_up,1); // up full
//printf("shared memory in full \n");
// read from C and kill if K messages have been sent
semop(full_out,&full_out_down,1); // down full
//if (strcmp(shm_out->line,"kill")!=0) printf("%s\n", shm_out->line);
if (strcmp(shm_out->line,"kill") == 0)
{
semop(empty_pid,&empty_pid_down,1);
shm_pid[j]=pid_match;
j++;
semop(full_pid,&full_pid_up,1);
printf("%d pid_match = %d\n",getpid(),pid_match );
printf("kill\n");
exit(1);
}
if (shm_out->pid == getpid())
{
//strcpy(shm_out->line,"\0"); shm_out->pid = 0;
printf("Pid's match\n");
pid_match++;
}
semop(empty_out,&empty_out_up,1); // empty up
}
//sleep(20);
}else if(child_pid < 0){
perror("fork failed\n");
}else
{
// break;
}
}
for (k=0; k<K; k++)
{
int j=0;
struct message m_out;
//printf("Consumer running\n");
semop(full_in,&full_in_down,1); //down full _in
//sleep(1);
//printf("Full got 'downed'\n");
m_out.pid = shm_in->pid;
while (shm_in->line[j] != '\0')
{
m_out.line[j] = toupper(shm_in->line[j]); // write in m_out->line the content of shm_in->line capitalized
j++;
}
/*if (k == K)
{
printf("kill\n");
strcpy(shm_out->line, "kill");
}*/
semop(empty_in,&empty_in_up,1); //up empty_in
semop(empty_out,&empty_out_down,1); // down empty_out
//printf("shm_in->line = %s \n", shm_in->line );
// m_out->line = shm_in->line; // capitalize & send
//strcpy(shm_out->line,m_out.line);
//shm_out->pid = m_out.pid;
printf("shm_in->line = %s \n", shm_in->line );
strcpy(shm_out->line,m_out.line);
printf("shm_out->line = %s\n", shm_out->line);
shm_out->pid = m_out.pid;
semop(full_out,&full_out_up,1); //up full
}
if (k == K)
{
printf("C kill\n");
semop(empty_out,&empty_out_down,1);
strcpy(shm_out->line, "kill");
semop(full_out,&full_out_up,1);
}
wait(NULL);
//sleep(2);
//printf("pid_match = %s\n",pid_match);
for(G=0; G<N; G++){
//sleep(2);
pid_match += shm_pid[G];
//printf("(pid_match = %s\n",pid_match);
if(G == N-1)
printf("Completed execution, exit %d\n",pid_match );
}
/* --- TERM ---*/
semctl(full_out,0,IPC_RMID,0);
semctl(full_in,0,IPC_RMID,0);
semctl(empty_out,IPC_RMID,0);
semctl(empty_in,0,IPC_RMID,0);
semctl(full_pid,0,IPC_RMID,0);
semctl(empty_pid,0,IPC_RMID,0);
shmdt(shm_pid);
shmdt(shm_in);
shmdt(shm_out);
}
return 0;
}
The wait function with a NULL argument only waits for one child process to exit. Then it stops waiting.
You need to wait for all processes to exit.
You can do that by saving all child-process pids, and then wait in a loop until they have all exited (checking using the return value of wait).
Trying to use a bounded buffer from a separate file that I've coded and it seems like that's where the code goes all crazy. Fairly new to C, and I was wondering if I am using the buffer the right way. The concept of instantiation isn't here, so if I just call one of the functions such as bbuff_blocking_insert will the array get initialized? How do I make the appropriate calls in order to get this working?
candy.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "bbuff.h"
#include <stdbool.h>
#include <time.h>
_Bool stop_thread = false;
typedef struct {
int source_thread;
double time_stamp_in_ms;
} candy_t;
double current_time_in_ms (void) {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now.tv_sec * 1000.0 + now.tv_nsec/1000000.0;
}
void* createCandy(void* arg) {
int r;
int factoryNumber = *(int*)arg;
while(!stop_thread) {
r = rand() % 4;
printf("Random Number: %d\n", r);
printf("\tFactory %d ship candy & wait %ds\n", factoryNumber, r);
candy_t *candy = (candy_t*)malloc(sizeof(candy_t));
candy->source_thread = factoryNumber;
candy->time_stamp_in_ms = current_time_in_ms();
bbuff_blocking_insert((void *)candy);
sleep(r);
}
printf("Candy-factory %d done\n", factoryNumber);
return 0;
}
void* extractCandy(void* arg) {
int r;
candy_t* candy;
while(true) {
candy = (candy_t*)bbuff_blocking_extract();
printf("Candy Source Thread: %d\n", candy->source_thread);
r = rand() % 2;
sleep(r);
}
return 0;
}
int main(int argc, char* argv[]) {
//Extract Arguments
if (argc <= 1) {
printf("Insufficient Arguments\n");
exit(-1);
}
int NO_FACTORIES = atoi(argv[1]);
int NO_KIDS = atoi(argv[2]);
int NO_SECONDS = atoi(argv[3]);
bbuff_init();
//Spawn Factory Threads
pthread_t ftids[NO_FACTORIES];
int factoryNumber[NO_FACTORIES];
for (int i = 0; i < NO_FACTORIES; i++) {
factoryNumber[i] = i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ftids[i], &attr, createCandy, &factoryNumber[i]);
}
//Spawn Kid Threads
pthread_t ktids [NO_KIDS];
for (int i = 0; i < NO_KIDS; i++) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&ktids[i], &attr, extractCandy, NULL);
}
//Wait for Requested Time
for (int i = 0; i < NO_SECONDS; i++) {
sleep(1);
printf("Time %ds\n", i+1);
}
//Stop Factory Threads
stop_thread = true;
for (int i = 0; i < NO_FACTORIES; i++) {
pthread_join(ftids[i], NULL);
}
//Wait until no more candy
while(bbuff_is_data_available()) {
printf("Waiting for all candy to be consumed");
sleep(1);
}
//Stop kid Threads
for (int i = 0; i < NO_KIDS; i++) {
pthread_cancel(ktids[i]);
pthread_join(ktids[i], NULL);
}
//Print Statistics
//Clean up any allocated memory
return 0;
}
bbuff.h
#ifndef BBUFF_H
#define BBUFF_H
#define QUEUE_SIZE 10
void bbuff_init(void);
void bbuff_blocking_insert(void* item);
void* bbuff_blocking_extract(void);
_Bool bbuff_is_data_available(void);
#endif
bbuff.c
#include "bbuff.h"
pthread_mutex_t mutex;
sem_t empty;
sem_t full;
int in = 0;
int out = 0;
int counter = 0;
void* buffer[QUEUE_SIZE];
void bbuff_init(void){
pthread_mutex_init(&mutex, NULL);
sem_init( &empty, 0, QUEUE_SIZE);
sem_init( &full, 0, 0);
}
void bbuff_blocking_insert(void* item) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
counter++;
buffer[in] = item;
in = (in+1) % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&full);
}
void* bbuff_blocking_extract(void) {
void* extractedItem;
sem_wait(&full);
pthread_mutex_lock(&mutex);
counter--;
extractedItem = buffer[out];
buffer[out] = NULL;
out = out % QUEUE_SIZE;
pthread_mutex_unlock(&mutex);
sem_post(&empty);
return extractedItem;
}
Output
$ ./candykids 1 1 10
Random Number: 3
Factory 0 ship candy & wait 3s
Candy Source Thread: 0
Time 1s
Time 2s
Random Number: 1
Factory 0 ship candy & wait 1s
Time 3s
Segmentation fault (core dumped)
In bbuff_blocking_extract(),
out = out % QUEUE_SIZE;
Should be:
out = (out+1) % QUEUE_SIZE;
So i am programming in c processes , and i need to create a timer that when it passes a certain point in my code it activates for x seconds, and then after the countdown timer hits 0 it does something. But in the meantime the code after the timer, needs to continue do to is work, following the flow of the code.
So in resume what i want to achieve is a countdown timer in c that when activated it creates another process were it counts the time and do something after.
Sorry if i did not explained this well enough.
Thanks in advance.
My code is the following so far i want to put the timer in the middle of the consumeTutuc method.
#include "sema.h"
#include <sys/shm.h>
//#include <sys/types.h>
#define MAX_CHILD 3 /* max. # of child processes */
#define LIFETIME 5 /* max. lifetime of a process */
#define MAX_NTIME 4 /* max. time for normal work */
#define MAX_CTIME 2 /* max. time for critical work */
#define N 10
#define SHMKEY (key_t) 0x10
#define SHMKEY2 (key_t) 0x11
#define SHMKEY3 (key_t) 0x12
#define SHMKEY4 (key_t) 0x13
//estruturas
typedef struct
{
int numeroPessoas;
char condicao;
}PESSOAS;
typedef struct
{
int id;
int espera;
}TUTUC;
int in, out, inP, outP, tt;
int *ptr; /*posicao do tuctuc*/
int *ptr2; /*numero disponiveis de tuctuc*/
PESSOAS *ptr3; /*fila de pessoas*/
int *ptr4; /*pessoas a espera*/
semaphore mutex, empty, full, emptyP, fullP, mutexP;
void produceTucTuc();
void consumeTucTuc();
void producePessoas();
void consumePessoas();
int main (void)
{
//MEMORIA
int shmid;
int shmid2;
int shmid3;
int shmid4;
char *addr;
char *addr2;
char *addr3;
char *addr4;
shmid = shmget(SHMKEY, N, 0777|IPC_CREAT);
shmid2 = shmget(SHMKEY2, N, 0777|IPC_CREAT);
shmid3 = shmget(SHMKEY3, N, 0777|IPC_CREAT);
shmid4 = shmget(SHMKEY4, N, 0777|IPC_CREAT);
addr=(char*)shmat(shmid,0,0);
addr2=(char*)shmat(shmid2,0,0);
addr3=(char*)shmat(shmid3,0,0);
addr4=(char*)shmat(shmid4,0,0);
ptr=(int*)addr;
ptr2=(int*)addr2;
ptr3=(PESSOAS*)addr3;
ptr4=(int*)addr4;
//MEMORIA
tt=1;
in=0;
out=0;
inP=0;
outP=0;
*ptr=0;
*ptr2=1;
//SEMAFOROS
full = init_sem(0);
empty = init_sem(N);
mutex = init_sem(1);
fullP = init_sem(0);
emptyP = init_sem(N);
mutexP = init_sem(1);
semaphore s;
//SEMAFOROS
int child_pid [MAX_CHILD], /* process ID's */
wait_pid;
int i, j,i2, /* loop variables */
child_stat; /* return status of child */
srand (time(NULL));
s = init_sem (1); /* create sem with value 1 */
for(i=0; i<10; i++){
produceTucTuc();
}
for (i = 0; i < MAX_CHILD; ++i)
{
child_pid [i] = fork ();
switch (child_pid [i])
{
case -1: /* error: no process created */
perror ("fork failed");
exit (1);
break;
case 0: /* child process */
/* up to Linux 2.0.x the process didn't terminate after
* LIFETIME seconds because "alarm()" and "sleep()" have
* used the same clock. This problem is solved in Linux 2.2.x
*/
if(i==0) produceTucTuc();
//if(i==1) consumeTucTuc();
if(i==1) producePessoas();
if(i==2) consumePessoas();
break;
default: /* parent process */
if (i == (MAX_CHILD - 1)) /* all childs created ? */
{ /* yes -> wait for termination */
for (j = 0; j < MAX_CHILD; ++j)
{
wait_pid = wait (&child_stat);
if (wait_pid == -1)
{
perror ("wait failed");
};
};
printf ("All child processes have terminated.\n");
//LIBERTA MEMORIA
rel_sem (s);
rel_sem (mutex);
rel_sem (empty);
rel_sem (full);
rel_sem (mutexP);
rel_sem (emptyP);
rel_sem (fullP);
shmdt(addr);
shmctl(shmid, IPC_RMID,NULL);
shmdt(addr2);
shmctl(shmid2, IPC_RMID,NULL);
shmdt(addr3);
shmctl(shmid3, IPC_RMID,NULL);
shmdt(addr4);
shmctl(shmid4, IPC_RMID,NULL);
//LIBERTA MEMORIA
};
}; /* end switch */
}; /* end for */
return 0;
}
void produceTucTuc(){
int ntuctuc;
alarm(LIFETIME);
//for(;;){
P(empty);
P(mutex);
*(ptr+in)=tt;
ntuctuc=*ptr2;
printf("------------------------------------\n");
printf("Produzi na pos %d o tuctuc %d\n",in,tt);
printf("Numero de TucTucs disponiveis:%d\n",ntuctuc);
in=(in+1)%N;
ntuctuc++;
*ptr2=ntuctuc;
tt=(tt+1)%N;
V(mutex);
V(full);
//}
}
void consumeTucTuc(){
int tuctuc;
int ntuctuc;
alarm(LIFETIME);
P(full);
P(mutex);
tuctuc=*(ptr+out);
ntuctuc=*ptr2;
ntuctuc--;
//printf("------------------------------------\n");
printf("Consumi na pos %d o tuctuc %d\n",out,tuctuc);
printf("Numero de TucTucs disponiveis:%d\n",ntuctuc);
out=(out+1)%N;
*ptr2=ntuctuc;
V(mutex);
V(empty);
}
void producePessoas(){
PESSOAS pessoa;
int espera =0;
alarm(LIFETIME);
for(;;){
P(emptyP);
P(mutexP);
if(rand()%5 == 0){
pessoa.numeroPessoas = 5;
}
else {
pessoa.numeroPessoas=rand()%5;
}
if(rand()%10<3){
pessoa.condicao = 'E';
}
else {
pessoa.condicao = 'N';
}
*(ptr3+inP)=pessoa;
espera=*ptr4;
espera=espera+pessoa.numeroPessoas;
*ptr4=espera;
printf("------------------------------------\n");
printf("Na pos %d entraram %d pessoas com %c condicao\n",inP,pessoa.numeroPessoas, pessoa.condicao);
printf("Estao %d pessoas à espera\n",*ptr4);
inP=(inP+1)%N;
V(mutexP);
V(fullP);
}
}
void consumePessoas(){
int pessoa;
int espera;
int p;
int aux;
alarm(LIFETIME);
while((*(ptr3 + outP)).numeroPessoas<(*ptr2)){
P(fullP);
P(mutexP);
pessoa=(*(ptr3+outP)).numeroPessoas;
espera=*ptr4;
espera=espera-pessoa;
*ptr4=espera;
printf("------------------------------------\n");
printf("Na pos %d sairam %d pessoas\n",inP,pessoa);
printf("Estao %d pessoas à espera\n",espera);
if(pessoa%2==1){
aux=(pessoa/2) + 1;
}else{
aux=pessoa/2;
}
for(p=0; p<aux; p++){
printf("%d\n",pessoa);
consumeTucTuc();
}
outP=(outP+1)%N;
V(mutexP);
V(emptyP);
}
}
This function you can call as a thread an it's a counter:
(You can build in a condition in the while loop and kill the thread!)
void counter( void *dummy ){
time_t start;
int weiter = 1,count = 0;
while (weiter) {
time(&start);
printf("\b\b\b\b%3i:",count);
while(difftime(time(NULL),start)<1);
count++;
//if condition kill thread
}
}
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.