Reputation: 13
I want to create a c code where I have to create Multiple Files using Multiple thread.
f = number of files to create,
t = number of threads
each output file should be named "file_<id>.bin
" where <id>
is a unique integer from 0 to (f-1) such that each of t threads creates approximately f/t of the files.
I am unable to approach this question using open(), close(), read() and write() functions of Linux.
I have written the code as:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
int isDirectoryExists(const char *path);
void *func(void *ptr);
int file;
int main(int argc, char *argv[])
{
pthread_t thread1;
int p;
p=1;
int f=atoi(argv[2]);
if (isDirectoryExists(argv[1]))
{
printf("Directory exists at path '%s'\n", argv[1]);
printf("Creating a new file at the Directory using Open Function");
for(int i = 1; i<=f; i++)
{
int number = i;
char index[20];
sprintf(index, "%d", number);
printf("\nThe number bring printed as the index of the file is:- %s", index);
char str[] = "unsorted_";
char str1[] = ".bin";
strcpy(str,index);
strcpy(str,str1);
file=open(str, O_CREAT | O_TRUNC | O_RDWR , 0666);
printf("file = %d/n", file);
if (file ==-1)
{
printf("Error Number % d\n", errno);
perror("Program");
}
pthread_create(&thread1, NULL, func, (void *)&p);
pthread_join(thread1, NULL);
close(file);
}
return 0;
}
else
{
printf("Directory does not exists at path '%s'\n", argv[1]);
}
}
void *func(void *ptr)
{
int *num;
int ret = -1;
num = (int *)ptr;
char buf[4] = {0};
printf("%d\n", *num);
printf("%d", *num);
memset(buf, 0, sizeof (buf));
snprintf(buf, sizeof *num, "%d", *num);
ret = write(file, buf, strlen(buf));
if (ret < 0)
printf("ret is %d, errno %d\n", ret, errno);
return 0;
}
int isDirectoryExists(const char *path)
{
struct stat stats;
stat(path, &stats);
if (S_ISDIR(stats.st_mode))
return 1;
return 0;
}
Upvotes: 0
Views: 156
Reputation: 132969
Your problem is not thread related, this code is basically broken:
int number = i;
char index[20];
sprintf(index, "%d", number);
char str[] = "unsorted_";
char str1[] = ".bin";
strcpy(str,index);
strcpy(str,str1);
Let's analyze it:
int number = i;
Why would you even do that? i
is already an int
. What purpose serves copying it?
char index[20];
sprintf(index, "%d", number);
Okay, you convert it to a string. You could just have used i
directly here instead of number
.
char str[] = "unsorted_";
char str1[] = ".bin";
Now you define two char arrays on stack and initialize them with string values.
strcpy(str,index);
And here is the first problem. You request that the content the pointer index
points to is copied and the result of the copy is written to the pointer str
. After this statement has executed, a new string exists in memory, it has the content of index
and str
points to it. This code is equivalent to:
char * temp = malloc(strlen(index) + 1);
memcpy(temp, index, strlen(index) + 1);
str = temp;
So str
now has the same value as index
and is no longer a stack pointer but points to dynamically allocated memory on the heap; which you never free by the way, so your code leaks memory.
Similar problem:
strcpy(str,str1);
This time str1
is copied and then str
will point to the copy. So in the end str
is always pointing to ".bin", which means all files your try to create are named ".bin" (so in fact only one file is created and that file is hidden as files starting with a period are hidden on UNIX systems (use ls -a
so see them).
A corrected version of the code may look like this:
const char * prefix = "unsorted_";
const char * extension = ".bin";
// Assuming that the number is never larger than 20 characters
// as in your code. + 1 is for the terminating NUL character.
size_t filenameSpace = strlen(prefix) + strlen(suffix) + 20 + 1;
char * filename = malloc(filenameSpace);
if (!filename) {
// Handle out of memory
}
if (snprintf(filename, "%s%d%s", prefix, i, suffix) == filenameSpace) {
// Handle too little space!
// Apparently the number was larger than 20.
}
file = open(filename, O_CREAT | O_TRUNC | O_RDWR , 0666);
free(filename); // Don't leak memory!
On some systems this can be done much easier:
char * filename = asprintf("unsorted_%d.bin", i);
if (!filename) {
// Handle out of memory
}
file = open(filename, O_CREAT | O_TRUNC | O_RDWR , 0666);
free(filename); // Don't leak memory!
But asprintf
is no standard C function, it's a BSD extension and not available on all systems.
Upvotes: 1