Segmentation Fault in C producer/consumer using messagequeue - c

I am doing an assignment that implements the producer / consumer problem using a UNIX message queue as the data structure shared by a single producer and three consumers. The program I am creating is supposed to create a child process and the child process will in turn create three threads. The parent process is to be the producer and the three threads will be the consumers. The number of items, N, that are to be produced will be provided to the program via the command line. After spawning the child process the parent will enter an N-iteration loop. In each iteration of the loop the parent will do the following:
1) Generate a random number, R, in the range of 0-999.
2) Send a message containing R.
3) Add R to a running total of all values produced.
4) Display the string “Producer produced a R”.
5) Put the producer to sleep for 0-1 seconds using sleep(rand()%2).
After the N iterations have completed display the string "Total produced = XXXX” (where XXXX is the sum of all R values produced) and wait for the child to terminate. It is the parent’s responsibility to create and destroy the queue.
The child process will create three consumer threads, 0, 1 and 2. Each thread will enter an N/3 iteration loop. In each iteration of the loop each consumer thread will do the following:
1) Read a message containing a value, C, consumed from the queue.
2) Add C to a running total maintained by each consumer thread.
3) Display the string “Consumer thread Z consumed a C” where Z is the thread number – 0,1 or 2.
4) Put the consumer thread to sleep for 1-3 seconds using sleep((rand()%3)+1)
After N/3 iterations display the string "Total consumed by consumer thread Z = YYYY” where YYYY is the sum of all N/3 values consumed.I am receiving a segmentation fault in the last iteration of the loop and I am not sure why. Can anyone help me with this issue?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/sem.h>
#include <semaphore.h>
struct msgbuf {
long mtype;
int mnum;
};
int msqid;
unsigned long total;
pthread_mutex_t sem_id;
int init() {
srand (time(NULL));
msqid = msgget(IPC_PRIVATE, IPC_CREAT | 0600);
if (msqid == -1) { perror("msgget"); return EXIT_FAILURE; }
pthread_mutex_init(&sem_id, NULL);
total = 0;
return 0;
}
int producer() {
int R = rand() % 999;
struct msgbuf msg = {999, R};
if(msgsnd(msqid, &msg, sizeof(msg.mnum) + 1, 0) == -1) {
perror("msgsnd"); return -1; }
total += R;
return R;
}
void *consumer(int thread_num, int iteration) {
struct msgbuf msg;
int thread_total = 0;
while(iteration--) {
pthread_mutex_lock(&sem_id);
if (msgrcv(msqid, &msg, sizeof(msg.mnum) + 1, 0, 0) == -1)
perror("msgrcv");
thread_total += msg.mnum;
printf("Consumer thread %d consumed a %d\n", thread_num, msg.mnum);
pthread_mutex_unlock(&sem_id);
}
printf("Total consumed by consumer thread %d = %d\n", thread_num,
thread_total);
sleep((rand()%3)+1);
}
int main(int argc, char *argv[]) {
int N = argc > 1 ? atoi(argv[1]) : 10;
if (init() != 0) return EXIT_FAILURE;
for (int i=0;i<N;i++) {
int R = producer();
if(R == -1) return EXIT_FAILURE;
printf("Producer produced a %d\n", R);
sleep(rand()%2);
}
printf("Total produced = %lu\n", total);
pthread_t thread_nums[3];
for (int i=0; i<=4; i++) {
int iteration = i == 0 ? N/3 + (N%3) : N/3;
if(pthread_create(&thread_nums[i], NULL,
consumer(i, iteration), NULL) != 0) {
perror("pthread_create");
return EXIT_FAILURE;
}
}
for (int i=0;i<4;i++) pthread_join(thread_nums[i], NULL);
return 0;
}

Ok so in the main function, thread_nums has 3 "slots", where as the loop proceeding wants to go over 5 different "slots".
Also, the last loop accesses a "slot" which does not exist
Remember that an array of size [3] has only three positions. The last item is at index 2 (0,1,2), for a total of three elements.

Related

Program is not generating random number and I am not sure why

#include<pthread.h>
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
#include<time.h>
#include<unistd.h>
#define ERROR_CREATE 1
#define ERROR_JOIN 2
// create the function to be executed as a thread
void *thread(void *ptr)
{
uintptr_t type = (uintptr_t) ptr; // thread number
srand(time(NULL) + getpid());
int wait = rand() % 10; // randomizes numbers from 0 to 10
sleep(wait); // waits in time intervals of seconds
printf("Thread - %ld waiting for %d seconds\n",type, wait);
return ptr; // returns the thread number
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Error with command line arguments");
}
int num_threads = atoi(argv[1]);
pthread_t threads[num_threads]; // array of thread types
for (long i = 1; i <= num_threads; i++) {
if (pthread_create(&threads[i], NULL, thread, (void *)i) != 0)
// if there's an error creating thread
{
fprintf(stderr,"Error: could not create thread");
return ERROR_CREATE;
}
}
// terminate each thread assigned
for (int i = 1; i <= num_threads; i++) {
if (pthread_join(threads[i], NULL) != 0)
// if there's an error ending each thread
{
fprintf(stderr, "Error: could not terminate thread");
return ERROR_JOIN;
}
}
return 0;
}
Seeding the rand function, I am still getting the same number outputted. I understand the hardware is fast and therefore is getting the same answer as the clock speed is faster than seeding the rand function. Does anyone know another way of getting more variety from the rand function?
Return if argv[1] is not populated otherwise it segfaults.
srand() resets the sequence. As you call it multiple times with the same value this is not what you want. Moved it main().
The array threads is accessed out of bounds in the two loops.
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define ERROR_CREATE 1
#define ERROR_JOIN 2
// create the function to be executed as a thread
void *thread(void *ptr) {
uintptr_t type = (uintptr_t) ptr; // thread number
int wait = rand() % 10; // randomizes numbers from 0 to 10
sleep(wait); // waits in time intervals of seconds
printf("Thread - %ld waiting for %d seconds\n",type, wait);
return ptr; // returns the thread number
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Error with command line arguments\n");
return 1;
}
srand(time(NULL));
int num_threads = atoi(argv[1]);
pthread_t threads[num_threads]; // array of thread types
for (long i = 0; i < num_threads; i++) {
if (pthread_create(&threads[i], NULL, thread, (void *)i) != 0)
// if there's an error creating thread
{
fprintf(stderr,"Error: could not create thread");
return ERROR_CREATE;
}
}
// terminate each thread assigned
for (int i = 0; i < num_threads; i++) {
if (pthread_join(threads[i], NULL) != 0)
// if there's an error ending each thread
{
fprintf(stderr, "Error: could not terminate thread");
return ERROR_JOIN;
}
}
}
and here is a couple of sample runs:
$ ./a.out 2
Thread - 1 waiting for 3 seconds
Thread - 2 waiting for 7 seconds
$ ./a.out 2
Thread - 1 waiting for 3 seconds
Thread - 2 waiting for 6 seconds

c program deals with multithreading

I need help with my c program, I have most of it done but it has some issues.
The program is about ** Exploring Synchronization Among Processes and Threads.**
You are given three (3) processes in one program that work together to solve a producer consumer problem:
2 processes are “producers” and each process produces its own type of product in a continuous loop. That is, one product type produced by one producer and a different product type by the other producer.
One Process is a “consumer” of products and consist of five (5) threads:
1 thread is a ‘distributor’ thread
two (2) threads consume one type of product (ex. consumes only product type 1)
two (2) threads consume a second type of product (ex. consumes only product type 2).
The consumer process contains two (2) product storage buffers, each comprised of a fixed number of slots. The number of slots in the buffers are to be different (one has more slots than
the other). You choose and specify the number of slots in each buffer as a definition in your
program solution
Communication between the producer processes and the consumer process is to be through a
single “pipe”. This single, shared pipe is used to communicate between each producer process
and the consumer process. Each producer process writes into this pipe the product to be
consumed by the consumer process.
Final program delivery: completion of the product consumer threads, output file design and
write functions; sample data runs with output files
I have most of it done but it has some issues.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <stdbool.h>
#include <fcntl.h>
#include <pthread.h>
#define BUFFER_SIZE1 20
#define BUFFER_SIZE2 30
typedef struct
{
int count;
int productType;
} product;
int count = 0;
int fd[2];
pthread_mutex_t lock;
pthread_cond_t cond;
typedef struct
{
product *values;
int head;
int tail;
int numEntries;
int size;
} queue;
queue q1;
queue q2;
void producer(int args);
void *consumer(void *args);
void *distributor(void *args);
void initQ(queue *q, int size);
bool QEmpty(queue *q);
bool QFull(queue *q);
bool put(queue *q, product prod);
product get(queue *q);
// https://www.youtube.com/watch?v=l6zkaJFjUbM
// https://www.geeksforgeeks.org/multithreading-c-2/
int main(int argc, char const *argv[])
{
// Creating 5 threads 4 consumer and 1 distributor
pthread_t th[5];
// Creating our pipe, fd[0] is read end, fd[1] is write end
if (pipe(fd) == -1)
{
perror("error creating pipe");
exit(1);
}
// Initializing both buffers
initQ(&q1, BUFFER_SIZE1);
initQ(&q2, BUFFER_SIZE2);
int pid1;
int pid2;
int consId1 = 1;
int consId2 = 2;
// Initializing lock
pthread_mutex_init(&lock, NULL);
// Initialziing condition variables
pthread_cond_init(&cond, NULL);
// Create first producer process using fork(), child process 1
if (pid1 = fork() == 0)
{
producer(1);
}
// Create second prodcuer process using fork(), child process 2
else if (pid2 = fork() == 0)
{
producer(2);
}
// Create distrubtor and consumer threads, parent process
else
{
// Creating 4 threads using for loop and pthread_create
for (int i = 0; i < 4; i++)
{
// 2 consumer threads for product type 1
if (i == 1 || i == 2)
{
if (pthread_create(&th[i], NULL, &consumer, &consId1) != 0)
{
perror("Error creating thread");
}
}
// 2 consumer threads for product type 2
else
{
if (pthread_create(&th[i], NULL, &consumer, &consId2) != 0)
{
perror("Error creating thread");
}
}
}
// use pthread_join to wait for preivous thread to terminate
for (int i = 0; i < 4; i++)
{
if (pthread_join(th[i], NULL) != 0)
{
perror("Error joining thread");
}
}
// Distributor thread
close(fd[1]);
while (1)
{
product prod;
// Using lock and condition variable around crit section to avoid race condition
// pthread_mutex_lock(&lock);
// pthread_cond_wait(&cond, &lock);
// Read from the pipe
read(fd[0], &prod, sizeof(prod));
if (prod.productType == 1)
{
put(&q1, prod);
}
else
{
put(&q2, prod);
}
}
// pthread_cond_signal(&cond);
// pthread_mutex_unlock(&lock);
// Close read end of the pipe
close(fd[0]);
}
return 0;
}
// Creating the producers
void producer(int args)
{
int prodCount = 0;
product prod;
prod.productType = args;
// Close read end of the pipe
close(fd[0]);
while (1)
{
prodCount++;
prod.count = prodCount;
// Send product to the pipe so the consumer can use
write(fd[1], &prod, sizeof(prod));
// Sleep for 0.01 - 0.2 seconds after each loop
int time = (rand() % (200000 - 10000 + 1)) + 10000;
usleep(time);
}
// Close write end of the pipe
close(fd[1]);
}
void *consumer(void *args)
{
int consCount1;
int consCount2;
FILE *fp;
fp = fopen("output.txt", "w");
product prod;
int prodType = *(int *)args;
while (1)
{
if (prodType == 1)
{
get(&q1);
consCount1++;
fprintf("Thread ID: %d\n", prodType);
fprintf(fp, "Product Type: %d\n", prod.productType);
fprintf(fp, "Production Sequence #: %d\n", prod.count);
fprintf(fp, "Consumption Sequence #: %d\n", consCount1);
}
else
{
get(&q2);
consCount2++;
fputs("Thread ID: 2\n", fp);
fprintf(fp, "Product Type: %d\n", prod.productType);
fprintf(fp, "Production Sequence #: %d\n", prod.count);
fprintf(fp, "Consumption Sequence #: %d\n", consCount2);
}
}
fclose(fp);
}
// https://www.youtube.com/watch?v=oyX30WVuEos&t=196s
// Circular buffer
void initQ(queue *q, int size)
{
q->size = size;
q->values = malloc(sizeof(product) * q->size);
q->numEntries = 0;
q->head = NULL;
q->tail = NULL;
}
// Checks if the queue is empty
bool QEmpty(queue *q)
{
return (q->numEntries == 0);
}
// Checks if the queue is full
bool QFull(queue *q)
{
return (q->numEntries == q->size);
}
// Used for adding products to the queue
bool put(queue *q, product prod)
{
// If the queue is full we can not add to it
if (QFull(q))
{
return false;
}
// Add product to the end of the queue
q->values[q->tail] = prod;
q->numEntries++;
// Move index of the tail
q->tail = (q->tail + 1);
// If index goes out of bounds set back to 0
if (q->tail >= q->size)
{
q->tail = 0;
}
return true;
}
// Used for removing products for the queue
product get(queue *q)
{
product result;
// If the queue is empty we can not dequeue anymore
if (QEmpty(q))
{
perror("Error on dequeue");
}
// Remove from the head of the queue
result = q->values[q->head];
q->head = (q->head + 1) & q->size;
q->numEntries--;
return result;
}
I suggest to revise the code to make it more readable since now it's quite hard to understand.
Here I point out some issues of your code that lead to errors:
if condition if (pidN = fork() == 0) {...}
you should fork() first and then check the pid:
int pidN = fork();
if (pidN == 0) {...}
fprintf() function fprintf("Thread ID: %d\n", prodType);
either write the function fputs or fprintf:
fputs("Thread ID: \n", fp);
or
fprintf(fp, "Thread ID: %d\n", prod.productType);
Parameter of the fprintf() function: pay attention to the variable you're passing since prodType does not exist.

shared memory with fork()

I would like to use shared memory with fork() but I can't seem to get the result I want.
So I have a car Structure array and I would like to put it in shared memory in order to use fork(). Then I want to run 10 fork() and wait until all the kids are done to display the results! (the result is just their total time of each car, it is different because I am generating a random number for each car).
The problem is when I printf() I have the same value for everyone, whereas it must be different for each child! because i tested with just a loop so without shared memory it works fine but i have to use shared memory;).
Could anyone help me please
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUMBER_OF_CARS 10
#define MIN 25000 // time generator
#define MAX 40000
typedef struct {
unsigned int totalTime;
} car;
car *shared_memory;
int drive(int i);
unsigned int generateNumber(void);
void display();
int main(void)
{
srand( time(NULL) );
/***************************************************
* Creating shared memory *
****************************************************/
int segment_id = shmget(IPC_PRIVATE, sizeof(car) * 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 *
**********************************************************/
int i;
pid_t pid = 0;
for (i = 0; i < NUMBER_OF_CARS; i++) {
pid = fork();
if (pid == 0)
break;
}
switch (pid) {
case -1:
perror("fork failed !");
exit(EXIT_FAILURE);
case 0:
drive(i); //540000
exit(EXIT_SUCCESS);
default:
display();
/******** wait for children to finish *********/
for (int j = 0; j < NUMBER_OF_CARS; j++) {
wait(NULL);
}
}
/******** Detach memory segments *********/
shmdt(shared_memory);
/******** Delete shared memory *********/
shmctl(segment_id, IPC_RMID, NULL);
exit(EXIT_SUCCESS);
}
unsigned int timeMaxi = 540000;
int drive( int i ) {
unsigned int number;
while ( shared_memory[i].totalTime <= timeMaxi ) //time pas dépassée
{
number = generateNumber();
shared_memory[i].totalTime += number;
}
return 0;
}
void display(void) {
for (int i = 0; i < NUMBER_OF_CARS; i++){
printf("Total %d : %d\n", i, shared_memory[i].totalTime);
}
}
unsigned int generateNumber(void)
{
return rand()%(MAX-MIN+1)+MIN;
}
The result :
./prog
Total 0 : 564634
Total 1 : 564634
Total 2 : 564634
Total 3 : 564634
Total 4 : 564634
Total 5 : 564634
Total 6 : 564634
Total 7 : 564634
Total 8 : 564634
Total 9 : 564634
There's nothing wrong with your shared memory. The problem is that all of the children are ending up with the same random number sequence in generateNumber(). You're only calling srand() once, before all the forks, so every child is going to generate the exact same random number.
Just call srand() in each child before calling drive(). srand(time(NULL)) won't be enough, because they'll likely all run within the same second, but you could use getpid() or some other appropriate method as an argument to srand() to seed the random number generator in each child differently.

Why is my semaphore lock not locking this process as expected? (Multithreading)

I'm currently writing a program that takes an array that has randomly generated numbers, and uses multithreading to essentially divide the array in equal parts, then each thread will find the minimum of their respective division of the array. Essentially, I need my parent thread to be blocked (have non-busy waiting for parallel processing efficiency) using semaphores while the child threads are looking for the minimum, however the combination of sem_wait and sem_post is not blocking the parent thread as expected.
I've attempted to change the sem_init parameters to different values, however it seems no matter what I do the parent doesn't actually get blocked.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/timeb.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#define MAX_SIZE 100000000
#define MAX_THREADS 16
#define RANDOM_SEED 8631
#define MAX_RANDOM_NUMBER 5000
// Global variables
long gRefTime; //For timing
int gData[MAX_SIZE]; //The array that will hold the data
int gThreadCount; //Number of threads
int gDoneThreadCount; //Number of threads that are done at a certain point. Whenever a thread is done, it increments this. Used with the semaphore-based solution
int gThreadMin[MAX_THREADS]; //The minimum value found by each thread
bool gThreadDone[MAX_THREADS]; //Is this thread done? Used when the parent is continually checking on child threads
int indices[MAX_THREADS][3];
// Semaphores
sem_t completed; //To notify parent that all threads have completed or one of them found a zero
sem_t mutex; //Binary semaphore to protect the shared variable gDoneThreadCount
int main(int argc, char *argv[]){
pthread_t tid[MAX_THREADS];
pthread_attr_t attr[MAX_THREADS];
int i, indexForZero, arraySize, min;
// Code for parsing and checking command-line arguments
if(argc != 4){
fprintf(stderr, "Invalid number of arguments!\n");
exit(-1);
}
if((arraySize = atoi(argv[1])) <= 0 || arraySize > MAX_SIZE){
fprintf(stderr, "Invalid Array Size\n");
exit(-1);
}
gThreadCount = atoi(argv[2]);
if(gThreadCount > MAX_THREADS || gThreadCount <=0){
fprintf(stderr, "Invalid Thread Count\n");
exit(-1);
}
indexForZero = atoi(argv[3]);
if(indexForZero < -1 || indexForZero >= arraySize){
fprintf(stderr, "Invalid index for zero!\n");
exit(-1);
}
GenerateInput(arraySize, indexForZero);
CalculateIndices(arraySize, gThreadCount, indices);
InitSharedVars();
SetTime();
// Initialize threads, create threads, and then make the parent wait on the "completed" semaphore
// The thread start function is ThFindMinWithSemaphore
sem_init(&mutex, 0, 1);
sem_init(&completed, 0, 0);
for(i=0; i < gThreadCount; i++){
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],ThFindMinWithSemaphore,&indices[i]);
}
sem_wait(&completed);
if(gThreadDone[i] == true && gThreadMin[i] == min){
for(i=0; i < gThreadCount; i++){
pthread_cancel(tid[i]);
}
}
min = SearchThreadMin();
printf("Threaded FindMin with parent waiting on a semaphore completed in %ld ms. Min = %d\n", GetTime(), min);
void* ThFindMinWithSemaphore(void *param) {
int threadNum = ((int*)param)[0];
int i;
int startIndex = indices[threadNum][1];
int endIndex = indices[threadNum][2];
sem_wait(&completed);
for (i = startIndex; i < endIndex; i++) {
if (gData[i] < gThreadMin[threadNum]){
gThreadMin[threadNum] = gData[i];
}
else if (gData[i] == 0){
sem_post(&completed);
pthread_exit(0);
}
}
sem_wait(&mutex);
gDoneThreadCount++;
sem_post(&mutex);
if (gDoneThreadCount == gThreadCount){
sem_post(&completed);
}
pthread_exit(0);
}
Note that this is not all of the file code that is actually in the file.
I want the main function to wait at the line where it says sem_wait(&completed). The goal is to have the child threads signal the parent by using sem_post when each thread is done searching for their minimum value, or one of the threads has found a zero within the array. Then at that point the main function should continue after receiving that sem_post signal.
As I understand, if the semaphore completed has a count of zero which I have initialized it to that using sem_init(&completed, 0, 0), the caller for sem_wait waits until it receives sem_post from one of the child threads. It appears that my program does not do the wait as expected.

Creating a process pool C Linux

I have an assignment and I am not quite sure how to go about it. Basically I have to create a coordinator process which creates 5 working processes which are waiting to be awakened. The coordinator passes a marker(integer) to the first process, then that process increments the marker by 1 and passes it to the next process. The coordinator process awakens the next process which does the same and so on. The so called marker should go through all the processes 10 times and in the end its value should be printed by the coordinator. Signals should be used as well as shared memory for the marker.
So I created 5 processes and I am thinking that on every iteration there should be a signal and a handler should be passed which will basically do all the work with the marker.
This is my first time working with processes. This is what I have so far:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <signal.h>
#define numOfProcesses 5
pid_t procIDs[5];
void handler(int signum){
//marker and all work here
}
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}else if(procIDs == 0){
pause();
}
}
}
int main(){
createProcesses();
int i;
for(i = 0; i < numOfProcesses; i++){
pkill(SIGUSR1, handler);
}
return 0;
}
I honestly don't know how to go about this. I would really appreciate a piece of advice. Thanks in advance!
This is what I have come up with. Sorry for answering, I couldn't find out how to format code in a comment. Anyway:
It should be 10 times each process. I am using shared memory so I guess I don't need a global variable for the marker? This is what I have come up with:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/shm.h>
#include<signal.h>
#include<sys/ipc.h>
#define numOfProcesses 5
#define numOfLoops 10
pid_t* procIDs[5];
void createProcesses(){
int i;
for(i = 0; i < numOfProcesses; i++){
procIDs[i] = fork();
if(procIDs[i] < 0 ){
perror("Fork error!");
}
else if(procIDs == 0){
pause();
}
}
}
void init(){//init marker = 0
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data;
data = (int*) shmat(shID, 0, 0);
*data = 0;
}
int* getValue(){//get value of marker
key_t mykey = ftok(".", 0);
int shID = shmget(mykey, sizeof(int), 0666 | IPC_CREAT);
int *data = shmat(shID, 0, 0);
return data;
}
void increment(int sig){//increment + 1
if(sig == SIGUSR1){
int temp;
int* data;
data = getValue();
temp = *data;
temp++;
*data = temp;
}
}
void yourFunc(int count, pid_t* mypid, int mysig){
if(count == 0){
return;
}else{
printf("Signal sent :: to PID : %d\n", mypid);
kill(*mypid, SIGUSR1);
yourFunc(count -1, ++mypid, SIGUSR1);
}
}
int main(){
signal(SIGUSR1, increment);
init();
int i,j;
createProcesses();
for(j = 0; j < numOfLoops; j++){//loop every pid 10 times
pid_t* currProcess = procIDs[0];
yourFunc(numOfProcesses, currProcess, SIGUSR1);
}
int* data = getValue();
printf("Marker: %d\n", *data);
return 0;
}
I tried your problem, but I am really baffled by the structure of your question, its really unclear what your problem statement is.
10 times each(10 times per process or a total of 10 times(2 times per process)
You say the processes are waiting to be awakened, which hints that they are not child processes rather other processes running on the system, and would require a fifo to communicate.
Nevertheless, the following is what I could conclude from the limited information.
You need to create a function which would be invoked 10 times(loop) by the coordinator on the first process(waiting to be awakened)
The function would recursively invoke the second process and so on till the last sleeping process.
You'll have to use SIGUSR1, and define action for it in a custom signal handler,
eg.
signal(SIGUSR1,custom_handler)
You will need to keep marker as a global variable.
Because C is a procedural language and kernel's scheduling is not in your hands once a process terminates you cannot recall it or ensure same PID for a process on forking.
So if you are thinking of creating processes inside functions which will be paused and on getting a signal shall resume, fine.....!, But it would be a one-off.
That's all I can say by the limited information your question presents.
Following is the above idea in C.
Initialise count = 5 (no. of processes)in the caller.
mypid points to the first process's PID.
void party_time(int count, pid_t* mypid, int mysig)
{
if(count == 0)
return;
else
{
printf("Signal sent :: to PID : %d\n",*mypid);
kill(*mypid,SIGUSR1);
party_time(count - 1 ,++mypid,SIGUSR1);
}
}

Resources