-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreadFile_fork.c
More file actions
359 lines (293 loc) · 12.7 KB
/
readFile_fork.c
File metadata and controls
359 lines (293 loc) · 12.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h> // Para fork(), getpid()
#include <sys/wait.h> // Para wait(), waitpid()
#include <sys/stat.h> // Para mkdir, stat
#include <dirent.h> // Para opendir, readdir
#include <time.h> // Para medir tiempo
#include "tree.h"
//--------------------------------------------------------------------------//
// //
// Funciones auxiliares para fork() //
// //
//--------------------------------------------------------------------------//
/**
* @brief Mide tiempo en milisegundos
* @return Tiempo actual en milisegundos
*/
long long getCurrentTimeMs() {
return (long long)((double)clock() * 1000 / CLOCKS_PER_SEC);
}
/**
* @brief Imprime información del proceso
* @param message Mensaje a mostrar
*/
void printProcessInfo(const char* message) {
printf("[PID %d] %s\n", getpid(), message);
fflush(stdout);
}
/**
* @brief Cuenta archivos regulares en un directorio
* @param inputDir Directorio a analizar
* @return Número de archivos regulares
*/
int countFilesInDirectory(const char* inputDir) {
DIR* dir = opendir(inputDir);
if (dir == NULL) {
return -1;
}
struct dirent* entry;
int count = 0;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char filepath[1024];
snprintf(filepath, sizeof(filepath), "%s/%s", inputDir, entry->d_name);
if (isRegularFile(filepath)) {
count++;
}
}
closedir(dir);
return count;
}
//--------------------------------------------------------------------------//
// //
// Compresión de directorio con fork() //
// //
//--------------------------------------------------------------------------//
/**
* @brief Comprime todos los archivos de un directorio usando procesos paralelos con fork()
* @param inputDir Directorio de entrada
* @param outputFile Archivo binario de salida
* @return true si la compresión fue exitosa, false en caso contrario
*/
bool compressDirectoryFork(const char* inputDir, const char* outputFile) {
printProcessInfo("Iniciando compresión de directorio con fork()");
long long startTime = getCurrentTimeMs();
DIR* dir;
struct dirent* entry;
FILE* output;
// Abrir el directorio
dir = opendir(inputDir);
if (dir == NULL) {
perror("Error al abrir el directorio");
return false;
}
// Contar archivos
int fileCount = countFilesInDirectory(inputDir);
if (fileCount <= 0) {
printf("No se encontraron archivos para comprimir\n");
closedir(dir);
return false;
}
printf("Archivos encontrados: %d\n", fileCount);
// Crear arrays para almacenar información de los archivos
char fileNames[fileCount][256];
char tempFiles[fileCount][1024];
pid_t childPids[fileCount];
int fileIndex = 0;
// Primera pasada: recopilar nombres de archivos
rewinddir(dir);
while ((entry = readdir(dir)) != NULL && fileIndex < fileCount) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char filepath[1024];
snprintf(filepath, sizeof(filepath), "%s/%s", inputDir, entry->d_name);
if (isRegularFile(filepath)) {
strcpy(fileNames[fileIndex], entry->d_name);
snprintf(tempFiles[fileIndex], sizeof(tempFiles[fileIndex]),
"/tmp/temp_compressed_fork_%d_%d.bin", getpid(), fileIndex);
fileIndex++;
}
}
closedir(dir);
printf("Creando %d procesos hijos para compresión paralela...\n", fileCount);
// Crear procesos hijos para comprimir archivos en paralelo
for (int i = 0; i < fileCount; i++) {
pid_t pid = fork();
if (pid == 0) {
// PROCESO HIJO: comprimir un archivo específico
char inputFilePath[1024];
snprintf(inputFilePath, sizeof(inputFilePath), "%s/%s", inputDir, fileNames[i]);
printProcessInfo("Comprimiendo archivo");
printf("[PID %d] Archivo: %s -> %s\n", getpid(), fileNames[i], tempFiles[i]);
// Comprimir el archivo
compressFile(inputFilePath, tempFiles[i]);
printProcessInfo("Compresión completada");
exit(0); // El hijo termina aquí
} else if (pid > 0) {
// PROCESO PADRE: guardar PID del hijo
childPids[i] = pid;
printf("[PID %d] Creado proceso hijo [PID %d] para: %s\n",
getpid(), pid, fileNames[i]);
} else {
// Error en fork()
perror("Error en fork()");
return false;
}
}
// PROCESO PADRE: esperar a que todos los hijos terminen
printProcessInfo("Esperando a que terminen todos los procesos hijos...");
for (int i = 0; i < fileCount; i++) {
int status;
waitpid(childPids[i], &status, 0);
printf("[PID %d] Proceso hijo [PID %d] terminado (archivo: %s)\n",
getpid(), childPids[i], fileNames[i]);
}
// Crear el archivo final combinando todos los archivos temporales
printProcessInfo("Combinando archivos comprimidos...");
output = fopen(outputFile, "wb");
if (output == NULL) {
perror("Error al crear el archivo de salida");
return false;
}
// Escribir número de archivos
fwrite(&fileCount, sizeof(int), 1, output);
// Combinar todos los archivos temporales
for (int i = 0; i < fileCount; i++) {
int nameLength = strlen(fileNames[i]);
fwrite(&nameLength, sizeof(int), 1, output);
fwrite(fileNames[i], sizeof(char), nameLength, output);
// Leer archivo temporal y obtener su tamaño
FILE* tempFile = fopen(tempFiles[i], "rb");
if (tempFile == NULL) {
fprintf(stderr, "Error al abrir archivo temporal: %s\n", tempFiles[i]);
continue;
}
fseek(tempFile, 0, SEEK_END);
long long compressedSize = ftell(tempFile);
fseek(tempFile, 0, SEEK_SET);
// Escribir tamaño y contenido
fwrite(&compressedSize, sizeof(long long), 1, output);
char buffer[4096];
size_t bytesRead;
while ((bytesRead = fread(buffer, 1, sizeof(buffer), tempFile)) > 0) {
fwrite(buffer, 1, bytesRead, output);
}
fclose(tempFile);
remove(tempFiles[i]);
printf("Archivo combinado: %s (%lld bytes)\n", fileNames[i], compressedSize);
}
fclose(output);
long long endTime = getCurrentTimeMs();
long long totalTime = endTime - startTime;
printf("\n=== COMPRESIÓN CON FORK() COMPLETADA ===\n");
printf("Archivos procesados: %d\n", fileCount);
printf("Tiempo total: %lld ms\n", totalTime);
printf("Archivo de salida: %s\n", outputFile);
return true;
}
//--------------------------------------------------------------------------//
// //
// Descompresión de directorio con fork() //
// //
//--------------------------------------------------------------------------//
/**
* @brief Descomprime un directorio usando procesos paralelos con fork()
* @param compressedFile Archivo comprimido
* @param outputDir Directorio de salida
* @return true si fue exitoso, false en caso contrario
*/
bool decompressDirectoryFork(const char* compressedFile, const char* outputDir) {
printProcessInfo("Iniciando descompresión de directorio con fork()");
long long startTime = getCurrentTimeMs();
FILE* input = fopen(compressedFile, "rb");
if (input == NULL) {
perror("Error al abrir el archivo comprimido");
return false;
}
// Crear directorio de salida
if (!createDirectoryIfNotExists(outputDir)) {
fclose(input);
return false;
}
// Leer número de archivos
int fileCount;
if (fread(&fileCount, sizeof(int), 1, input) != 1) {
fprintf(stderr, "Error al leer el número de archivos\n");
fclose(input);
return false;
}
printf("Descomprimiendo %d archivos con fork()...\n", fileCount);
// Arrays para almacenar información
char fileNames[fileCount][256];
char tempCompressedFiles[fileCount][1024];
char outputFilePaths[fileCount][1024];
pid_t childPids[fileCount];
// Extraer todos los archivos comprimidos a archivos temporales
for (int i = 0; i < fileCount; i++) {
int nameLength;
fread(&nameLength, sizeof(int), 1, input);
fread(fileNames[i], sizeof(char), nameLength, input);
fileNames[i][nameLength] = '\0';
long long compressedSize;
fread(&compressedSize, sizeof(long long), 1, input);
// Crear archivo temporal
snprintf(tempCompressedFiles[i], sizeof(tempCompressedFiles[i]),
"/tmp/temp_extract_fork_%d_%d.bin", getpid(), i);
snprintf(outputFilePaths[i], sizeof(outputFilePaths[i]),
"%s/%s", outputDir, fileNames[i]);
FILE* tempFile = fopen(tempCompressedFiles[i], "wb");
if (tempFile == NULL) {
fprintf(stderr, "Error al crear archivo temporal para: %s\n", fileNames[i]);
continue;
}
// Copiar datos comprimidos
char buffer[4096];
long long bytesRemaining = compressedSize;
while (bytesRemaining > 0) {
size_t bytesToRead = (bytesRemaining < sizeof(buffer)) ? bytesRemaining : sizeof(buffer);
size_t bytesRead = fread(buffer, 1, bytesToRead, input);
fwrite(buffer, 1, bytesRead, tempFile);
bytesRemaining -= bytesRead;
}
fclose(tempFile);
printf("Extraído archivo temporal: %s\n", fileNames[i]);
}
fclose(input);
// Crear procesos hijos para descomprimir en paralelo
printf("Creando %d procesos hijos para descompresión paralela...\n", fileCount);
for (int i = 0; i < fileCount; i++) {
pid_t pid = fork();
if (pid == 0) {
// PROCESO HIJO: descomprimir un archivo específico
printProcessInfo("Descomprimiendo archivo");
printf("[PID %d] Archivo: %s -> %s\n", getpid(), fileNames[i], outputFilePaths[i]);
if (decompressFile(tempCompressedFiles[i], outputFilePaths[i])) {
printProcessInfo("Descompresión completada");
} else {
printProcessInfo("Error en descompresión");
}
// Limpiar archivo temporal
remove(tempCompressedFiles[i]);
exit(0);
} else if (pid > 0) {
// PROCESO PADRE: guardar PID
childPids[i] = pid;
printf("[PID %d] Creado proceso hijo [PID %d] para: %s\n",
getpid(), pid, fileNames[i]);
} else {
perror("Error en fork()");
return false;
}
}
// PROCESO PADRE: esperar a todos los hijos
printProcessInfo("Esperando a que terminen todos los procesos hijos...");
for (int i = 0; i < fileCount; i++) {
int status;
waitpid(childPids[i], &status, 0);
printf("[PID %d] Proceso hijo [PID %d] terminado (archivo: %s)\n",
getpid(), childPids[i], fileNames[i]);
}
long long endTime = getCurrentTimeMs();
long long totalTime = endTime - startTime;
printf("\n=== DESCOMPRESIÓN CON FORK() COMPLETADA ===\n");
printf("Archivos procesados: %d\n", fileCount);
printf("Tiempo total: %lld ms\n", totalTime);
printf("Directorio de salida: %s\n", outputDir);
return true;
}