I cant even get to print "Main" on the screen. It seems like none of my code runs. When i dont specify any command line arguments in prints out the warning. my input file contains integers on each line.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
int patientCount,treatedPatientCount,maxPatient,allRegistered;
int *list;
FILE *input,*output;
sem_t semOutputFile,semGlobalVars;
void* Nurse();
void* Doctor(void *);
int main( int argc, char *argv[] ){
printf("Main");
if(argc != 3){
printf("Command line argument count is different then expected. Aborting!");
return -1;
}
input = fopen(argv[1],"r");
output = fopen(argv[2],"w");
allRegistered = 0;
maxPatient = 5;
treatedPatientCount = 0;
patientCount = 0;
list = malloc(sizeof(int)*maxPatient);
pthread_t nurse,doc1,doc2;
sem_init(&semGlobalVars, 0, 1);
sem_init(&semOutputFile, 0, 1);
pthread_create(&nurse, NULL, &Nurse, NULL);
pthread_create(&doc1, NULL, &Doctor, (void*) 1);
pthread_create(&doc2, NULL, &Doctor, (void*) 2);
pthread_exit(NULL);
}
void* Nurse(){
char buff[255],*eof;
while(1){
eof = fgets(buff, 255, input);
if (eof == NULL) {
allRegistered = 1;
pthread_exit(NULL);
}
int k = atoi(buff);
sem_wait(&semGlobalVars);//Critical region 1 starts
if(patientCount == maxPatient){
maxPatient *=2;
list = realloc(list,sizeof(int)*maxPatient);
}
list[patientCount++] = k;
sem_post(&semGlobalVars);//Critical region 1 ends
sem_wait(&semOutputFile);//Critical region 2 starts
fputs("Nurse registered a patient!\n",output);
sem_post(&semOutputFile);//Critical region 2 ends
sleep(2);
}
}
void* Doctor(void * id){
printf("Doctor");
char buff[255];
int waitTime = 0;
while(1){
printf("%d %d %d",allRegistered,treatedPatientCount,patientCount);
if(allRegistered == 1 && treatedPatientCount==patientCount) pthread_exit(NULL);
sem_wait(&semGlobalVars);//Critical region 1 starts
waitTime = list[treatedPatientCount++];
sem_post(&semGlobalVars);//Critical region 1 ends
sprintf (buff, "Doctor %d treated a patient\n", (int) id);
sem_wait(&semOutputFile);//Critical region 2 starts
fputs(buff,output);
sem_post(&semOutputFile);//Critical region 2 ends
sleep(waitTime);
}
}
You can add exit(0) to the end of main
What exit(0) does is flush all buffers, (and other good things,) making sure anything that was buffered (like that printf of "Main") gets written out.
All C streams (open with functions in <cstdio>) are closed (and flushed, if buffered), and all files created with tmpfile are removed.
http://www.cplusplus.com/reference/cstdlib/exit/
Related
I have 2 threads and they should use the same memory. Main method should start both threads. Trå A must read the contents of a file and share it with Trå B. Trå B must also receive the data that Trå A has shared and loop through and count the number of bytes in the file. Both Threads run but on the last step before the program terminates before I memory segment fault. I use Semaphore to communicate between the Threads. here i my code:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFFER_SIZE 4096
typedef struct _Buffer
{
int size;
char data[BUFFER_SIZE];
} Buffer;
sem_t task1, task2;
void *thread_A(void *arg);
void *thread_B(void *arg);
int main(int argc, char *argv[])
{
Buffer *memory = malloc(sizeof(Buffer));
sem_init(&task1, 0, 0);
sem_init(&task2, 0, 0);
pthread_t thread_A_id;
pthread_t thread_B_id;
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
if (pthread_join(thread_A_id, NULL) != 0)
{
perror("Error joining thread A");
exit(1);
}
if (pthread_join(thread_B_id, NULL) != 0)
{
perror("Error joining thread B");
exit(1);
}
free(memory);
return 0;
}
void *thread_A(void *arg)
{
Buffer *buffer = (Buffer*) arg;
FILE *pdf_file = fopen("file.pdf", "rb");
if (pdf_file == NULL)
{
perror("Can not open the file");
}
printf("size of struct %ld\n", sizeof(Buffer));
buffer->size = fread(&buffer->data, sizeof(char), BUFFER_SIZE, pdf_file);
fclose(pdf_file);
sem_post(&task1);
sem_wait(&task2);
printf("A is out\n");
return NULL;
}
void *thread_B(void *arg)
{
printf("IAM IN TREAD B");
Buffer *buffer = (Buffer*) arg;
sem_wait(&task1);
int i=0;;
int byte_counts[256] = {0};
while (buffer->size != i) {
unsigned char byte = buffer->data[i];
byte_counts[byte]++;
i++;
}
for (int i = 0; i < 256; i++)
{
printf("Byte-value %02X: %d\n", i, byte_counts[i]);
}
sem_post(&task2);
printf("threadB is done 2\n");
return NULL;
}
memory is a pointer to a Buffer (Buffer *), and by taking its address, you get a pointer to a pointer to a buffer (Buffer **):
Buffer *memory = malloc(sizeof(Buffer));
...
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
But in the thread functions, you're assuming that arg is a Buffer *:
Buffer *buffer = (Buffer*) arg;
This causes undefined behaviour.
Clearly there's one indirection too many; memory is already a pointer so we don't need to take its address:
pthread_create(&thread_A_id, NULL, &thread_A, memory);
pthread_create(&thread_B_id, NULL, &thread_B, memory);
If file fails to open, fread will return -1 and it's not checked. So the loop in thread_B will read first garbage from buffer->data and then will continue out of limit (because of comparison with -1).
So, at first, there is missing handling of error from fopen() - thread_a continues after perror, second - missing error check after fread().
By the way, the check for
if (buffer->size == i)
after while (buffer->size != i) is superfluous :)
I have a large file (around 1,000,000 characters) in the format "AATACGTAGCTA" and a subsequent file, such as "CGTATC" (10,240 characters). I want to find the largest match of the subsequence within the main sequence. A full, 100% subsequence match may not exist, this is not guaranteed. For the sake of a smaller example, the above would output: Longest match is 4/6 starting at position 5.
I'm working on my C basics, and would like to implement it like so:
The user chooses how many processes they would like to split the work
into.
Each process does 1/nth of the work and updates the shared memory
values located in the struct.
The longest match (it may not be all characters) is reflected in the
struct, as well as it's starting position, and how many
characters were matched. See output below.
Code
#define _GNU_SOURCE
#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <semaphore.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/shm.h>
typedef struct memoryNeeded {
int start_pos, total_correct;
char sequence[1038336];
char subsequence[10240];
sem_t *sem;
} memoryNeeded;
// Used to check all arguments for validity
int checkArguments(char* p, int argc) {
char *prcs;
errno = 0;
int num;
long conv = strtol(p, &prcs, 10);
if (errno!= 0 || *prcs != '\0' || conv > INT_MAX || conv > 50) {
puts("Please input a valid integer for number of processes. (1-50)");
exit(1);
} else {
num = conv;
if (argc != 4) {
puts("\nPlease input the correct amount of command line arguments (4) in"
"the format: \n./DNA (processes) (sequence) (subsequence)\n");
exit(1);
} else
printf("Looking for string using %d processes...\n", num);
return(num);
}
}
int main (int argc, char* argv[]) {
int processes = checkArguments(argv[1], argc);
key_t shmkey;
int procNumber, shmid, pid;
FILE *sequence;
FILE *subsequence;
char *buf1, *buf2;
// Create shared memory
size_t region_size = sizeof(memoryNeeded);
shmkey = ftok("ckozeny", 5);
shmid = shmget(shmkey, region_size, 0644 | IPC_CREAT);
if (shmid < 0) {
perror("shmget\n");
exit(1);
}
// Create structure in shared memory, attach memory and open semaphore
memoryNeeded *mn;
mn = (memoryNeeded *)shmat(shmid, NULL, 0);
mn->sem = sem_open("sem", O_CREAT | O_EXCL, 0644, 1);
sequence = fopen(argv[2], "r");
subsequence = fopen(argv[3], "r");
// Get file sizes
fseek(sequence, 0L, SEEK_END);
int sz1 = ftell(sequence);
rewind(sequence);
fseek(subsequence, 0L, SEEK_END);
int sz2 = ftell(subsequence);
rewind(subsequence);
// Read files into 2 buffers, which are put into struct mn
buf1 = malloc(sz1);
buf2 = malloc(sz2);
if (sz1 != fread(buf1, 1, sz1, sequence)) {
free(buf1);
}
if (sz2 != fread(buf2, 1, sz2, subsequence)) {
free(buf2);
}
// Initialize struct with necessary values
mn->start_pos = 0;
mn->total_correct = 0;
strncpy(mn->sequence, buf1, sz1);
strncpy(mn->subsequence, buf2, sz2);
fclose(sequence);
fclose(subsequence);
// Begin n forks
for (procNumber = 0; procNumber < processes; procNumber++) {
pid = fork();
if (pid < 0) {
sem_unlink("sem");
sem_close(mn->sem);
printf ("Fork error.\n");
} else if (pid == 0)
break;
}
if (pid != 0) {
while ((pid = waitpid (-1, NULL, 0))){
if (errno == ECHILD)
break;
}
printf("Best match is at position %d with %d/10240 correct.", mn->start_pos, mn->total_correct);
printf ("\nParent: All children have exited.\n");
sem_unlink("sem");
sem_close(mn->sem);
shmdt(mn);
shmctl(shmid, IPC_RMID, 0);
exit(0);
} else {
// this child process will do its 1/nth of the work
sem_wait(mn->sem);
printf ("Child(%d) is in critical section.\n", procNumber);
sleep(1);
int i = 0;
int longest, count = 0;
for (i = 0; i < sz1; i += processes) {
for (int j = 0; j < sz2; j += processes) {
count = 0;
while (mn->sequence[i+j] == mn->subsequence[j]) {
count++;
j++;
}
if (count > longest) {
longest = count;
}
}
}
// If local match is longer than that of the struct, update and unlock
if (longest > mn->total_correct) {
mn->total_correct = count;
mn->start_pos = (i - count);
sem_post(mn->sem);
} else
// If not - unlock and let next process go
sem_post(mn->sem);
exit(0);
}
return 1;
}
The current child code is more or less "pseudocode". I've put it together how it makes sense in my head. (I'm aware this may not be correct or function as intended.) My question is in regard to the child code algorithm near the bottom.
How do I implement this so each child does 1/nth of the work, and finds the longest match, even though it may not match 100%?
Final output would be:
./DNA 6 sequence1 subsequence1
Looking for string using 6 processes...
Best match is at position 123456 with 9876/10240 correct.
Thanks.
I am trying to read a file with aio.h byte by byte using aio_read with a number of threads. But I don't know if I am on the right track since there are not so many stuff to read on the Internet.
I have just created a worker function to pass it to my threads. And also as an argument to pass to the thread, I created a struct called thread_arguments and I pass a few necessary arguments in it, which will be needed for aiocb such as offset, file_path to open, buffer size, and priority.
I can read a file with one thread from start to end successfully. But when it comes to reading a file as chunks from within a few threads, I couldn't make it. And I am not even sure if I can do that with aio->reqprio without using semaphores or mutexes. (Trying to open a file from within a few threads at the same time?)
How can I read a few number of bytes from within a few threads asynchronously?
Let's say the file contains "foobarquax" and we have three threads using aio library.
Then first one should read "foo",
the second should read "bar" and
the last one should read "quax" asynchronously.
You can see screenshots of issues regarding running it with multiple threads on here
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <aio.h>
#include <string.h>
#include <fcntl.h> // open -> file descriptor O_RDONLY, O_WRONLY, O_RDWR
#include <errno.h>
#include <unistd.h>
typedef struct thread_args {
char *source_path;
char *destination_path;
long int buffer_size;
long int buffer_size_last; // buffer size for the last thread in case there is a remainder.
long int offset;
int priority;
} t_args;
void *worker(void *thread_args) {
t_args *arguments = (t_args *) thread_args;
struct aiocb *aiocbRead;
aiocbRead = calloc(1, sizeof(struct aiocb));
aiocbRead->aio_fildes = open(arguments->source_path, O_RDONLY);
if (aiocbRead->aio_fildes == -1) {
printf("Error");
}
printf("opened on descriptor %d\n", aiocbRead->aio_fildes);
aiocbRead->aio_buf = malloc(sizeof(arguments->buffer_size));
aiocbRead->aio_offset = arguments->offset;
aiocbRead->aio_nbytes = (size_t) arguments->buffer_size;
aiocbRead->aio_reqprio = arguments->priority;
int s = aio_read(aiocbRead);
if (s == -1) {
printf("There was an error");
}
while (aio_error(aiocbRead) == EINPROGRESS) {}
printf("Bytes read %ld", aio_return(aiocbRead));
close(aiocbRead->aio_fildes);
for (int i = 0; i < arguments->buffer_size ; ++i) {
printf("%c\n", (*((char *) aiocbRead->aio_buf + i)));
}
}
// Returns a random alphabetic character
char getrandomChar() {
int letterTypeFlag = (rand() % 2);
if (letterTypeFlag)
return (char) ('a' + (rand() % 26));
else
return (char) ('A' + (rand() % 26));
}
void createRandomFile(char *source, int numberofBytes) {
FILE *fp = fopen(source, "w");
for (int i = 0; i < numberofBytes; i++) {
fprintf(fp, "%c", getrandomChar());
}
fclose(fp);
}
int main(int argc, char *argv[]) {
char *source_path = argv[1];
char *destination_path = argv[2];
long int nthreads = strtol(argv[3], NULL, 10);
// Set the seed.
srand(time(NULL));
// Get random number of bytes to write to create the random file.
int numberofBytes = 10 + (rand() % 100000001);
// Create a random filled file at the source path.
createRandomFile(source_path, 100);
// Calculate the payload for each thread.
long int payload = 100 / nthreads;
long int payloadLast = payload + 100 % nthreads;
// Create a thread argument to pass to pthread.
t_args *thread_arguments = (t_args *) malloc(nthreads * sizeof(t_args));
for (int l = 0; l < nthreads; ++l) {
// Set arguments in the struct.
(&thread_arguments)[l]->source_path = source_path;
(&thread_arguments)[l]->destination_path = destination_path;
(&thread_arguments)[l]->buffer_size = payload;
(&thread_arguments)[l]->buffer_size_last = payloadLast;
(&thread_arguments)[l]->offset = l * payload;
(&thread_arguments)[l]->priority = l;
}
pthread_t tID[nthreads];
// Create pthreads.
for (int i = 0; i < nthreads; ++i) {
pthread_create(&tID[i], NULL, worker, (void *) &thread_arguments[i]);
}
// Wait for pthreads to be done.
for (int j = 0; j < nthreads; ++j) {
pthread_join(tID[j], NULL);
}
free(thread_arguments);
return 0;
}
This code is reading succesfully if I just call it from one thread but doesn't work if I use it for more than one threads which is what I want.
I'm new to pthread and multithreading, i have written a code like that.
#include <pthread.h>
#include <unistd.h>
void *nfc_read(void *arg)
{
int fd = -1;
int ret;
uint8_t read_data[24];
while(1){
ret = read_block(fd, 8, read_data);
if(!ret){
return (void)read_data;
}
}
}
int main(int argc, char *argv[])
{
pthread_t my_thread;
void *returnValue;
pthread_create(&my_thread, NULL, nfc_read, NULL);
pthread_join(my_thread, &returnValue);
printf("NFC card value is : %s \n", (char)returnValue);
printf("other process");
return 0;
}
Until the return value from nfc_read function, as I will have other code I need to run and I don't want to block in main. How can i do that?
This is a sample where a read thread runs concurrently to the "main" thread which is doing other work (in this case, printing dots and sleeping).
To keep things simple, a simulated the reading from an input device with copying a constant string character by character. I guess, this is reasonable as the synchronization of threads is focused.
For the synchronization of threads, I used atomic_bool with atomic_store() and atomic_load() which are provided by the Atomic Library (since C11).
My sample application test-concurrent-read.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
/* sampe input */
const char sampleInput[]
= "This is sample input which is consumed as if it was read from"
" a (very slow) external device.";
atomic_bool readDone = ATOMIC_VAR_INIT(0);
void* threadRead(void *pArg)
{
char **pPBuffer = (char**)pArg;
size_t len = 0, size = 0;
int c; const char *pRead;
for (pRead = sampleInput; (c = *pRead++) > 0; sleep(1)) {
if (len + 1 >= size) {
if (!(*pPBuffer = realloc(*pPBuffer, (size + 64) * sizeof(char)))) {
fprintf(stderr, "ERROR! Allocation failed!\n");
break;
}
size += 64;
}
(*pPBuffer)[len++] = c; (*pPBuffer)[len] = '\0';
}
atomic_store(&readDone, 1);
return NULL;
}
int main()
{
/* start thread to read concurrently */
printf("Starting thread...\n");
pthread_t idThreadRead; /* thread ID for read thread */
char *pBuffer = NULL; /* pointer to return buffer from thread */
if (pthread_create(&idThreadRead, NULL, &threadRead, &pBuffer)) {
fprintf(stderr, "ERROR: Failed to start read thread!\n");
return -1;
}
/* start main loop */
printf("Starting main loop...\n");
do {
putchar('.'); fflush(stdout);
sleep(1);
} while (!atomic_load(&readDone));
putchar('\n');
void *ret;
pthread_join(idThreadRead, &ret);
/* after sync */
printf("\nReceived: '%s'\n", pBuffer ? pBuffer : "<NULL>");
free(pBuffer);
/* done */
return 0;
}
Compiled and tested with gcc in cygwin on Windows 10 (64 bit):
$ gcc -std=c11 -pthread -o test-concurrent-read test-concurrent-read.c
$ ./test-concurrent-read
Starting thread...
Starting main loop...
.............................................................................................
Received: 'This is sample input which is consumed as if it was read from a (very slow) external device.'
$
I guess, it is worth to mention why there is no mutex guarding for pBuffer which is used in main() as well as in threadRead().
pBuffer is initialized in main() before pthread_create() is called.
While thread_read() is running, pBuffer is used by it exclusively (via its passed address in pPBuffer).
It is accessed in main() again but not before pthread_join() which grants that threadRead() has ended.
I tried to find a reference by google to confirm that this procedure is well-defined and reasonable. The best, I could find was SO: pthread_create(3) and memory synchronization guarantee in SMP architectures which cites The Open Group Base Specifications Issue 7 - 4.12 Memory Synchronization.
I am working on pipeline system with string in C. For example I write this line to console ./pipeline LOWERCASE REVWORD SQUASHWS < stringFile.txt. It should be any like this P0 -> P1 -> P2 -> ...-> Pn. P0 load string from file stringFile.txt and send it to P1.. I can work with pipe(send and read), but I dont know how to work with N processes. It should be any like this. Can you give me any advice or example? Thank you
while(is_something_to_read) {
load_from_previous_process();
do_process(); // for example LOWERCASE
send_to_next_process();
}
Patrik,
I wrote a program that simulate a shell that will spawn a given amount of children and each process will then communicate with another process. Since the number of processes can vary I decided to use a 2D array for the pipes. In the below code NUM_PROCS refers to the amount of processes that will be running (including the parent).
I declare it
int pipes[NUM_PROCS][2];
After this, I create the pipes
for(i = 0; i < NUM_PROCS; i++)
{
if((pipe(pipes[i])) < 0)
{
perror("Failed to open pipe");
}
}
This is a shell program that i wrote for practise.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define MAXARGS 256
char ** getargs(char * cmd) {
char** argsarray;
int nargs = 0;
int nlen = strlen(cmd);
int i = 0;
argsarray = (char**) malloc(sizeof(char*) * MAXARGS);
argsarray[0] = strtok(cmd," ");
i = 0;
while (argsarray[i] != NULL){
i++;
argsarray[i] = strtok(NULL," ");
}
return argsarray;
}
int main(void){
pid_t childpid;
int fd[256][2];
char cmd[256];
char * sepCmd[256];
char * pch;
printf("Please enter a command sequence: \n");
gets(cmd);
printf("You have entered: %s ....%d\n", cmd,strlen(cmd));
printf("Attempting to split up command: \n");
pch = strtok (cmd, "|");
int count = 0;
while (pch != NULL && count < 256) {
printf("%s\n", pch);
sepCmd[count] = pch;
printf("The value in this array value is: %s\n", sepCmd[count]);
pch = strtok (NULL, "|");
count++;
}
char ** argue;
int k;
/* Block that deals with the first command given by the user */
k = 0;
pipe(fd[k]);
if(!fork()) {
dup2(fd[k][1], STDOUT_FILENO);
close(fd[k][0]);
argue = getargs(sepCmd[k]);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}
/*Loop that will control all other comands except the last*/
for(k = 1; k <= count - 2; k++) {
close(fd[k-1][1]);
pipe(fd[k]);
if(!fork()) {
close(fd[k][0]);
dup2(fd[k-1][0], STDIN_FILENO);
dup2(fd[k][1], STDOUT_FILENO);
argue = getargs(sepCmd[k]);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}
}
/*Block that will take care of the last command in the sequence*/
k = count - 1;
close(fd[k-1][1]);
if(!fork()) {
dup2(fd[k-1][0], STDIN_FILENO);
argue = getargs(sepCmd[k]);
execvp(argue[0], argue);
perror(argue[0]);
exit(0);
}
while(waitpid(-1, NULL, 0) != -1);
}