我正在研究如何从多个进程登录到单个文件并遇到一些问题。
首先,我编写了以下代码而没有记录模块:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "get_next_line.h"
int my_putstr(char *str)
{
int i;
if (str == NULL)
return (1);
i = 0;
while (str[i] != '\0')
{
write(1, &str[i], 1);
i = i + 1;
}
return (0);
}
char *my_strcpy(char *src, char *dest)
{
int i;
int r;
r = 0;
i = 0;
if (src == NULL)
return (dest);
while (dest != NULL && dest[i] != '\0')
i = i + 1;
while (src[r] != '\0')
{
dest[i] = src[r];
i = i + 1;
r = r + 1;
}
dest[i] = '\0';
return (dest);
}
int check_back_n(t_stock *stock)
{
int i;
if (stock->save == NULL)
return (1);
i = 0;
while (stock->save[i] != '\0')
{
if (stock->save[i] == '\n')
return (0);
i = i + 1;
}
return (1);
}
int my_realloc(t_stock *stock)
{
if ((stock->temp = malloc(sizeof(char) *
(READ_SIZE * stock->counter) + 1)) == NULL)
return (1);
stock->temp = my_strcpy(stock->save, stock->temp);
free(stock->save);
if ((stock->save = malloc(sizeof(char) *
(READ_SIZE * (stock->counter + 1)) + 1)) == NULL)
return (1);
stock->save = my_strcpy(stock->temp, stock->save);
free(stock->temp);
return (0);
}
char *fill_over(t_stock *stock, char *over)
{
stock->r = 0;
stock->i = 0;
while (stock->save[stock->i] != '\n')
stock->i = stock->i + 1;
stock->save[stock->i] = '\0';
stock->i = stock->i + 1;
if ((over = malloc(sizeof(char) * READ_SIZE) + 1) == NULL)
return (NULL);
while (stock->save[stock->i] != '\0')
{
stock->save[stock->i] = over[stock->r];
stock->save[stock->i] = '\0';
stock->i = stock->i + 1;
stock->r = stock->r + 1;
}
return (over);
}
char *get_next_line(const int fd)
{
t_stock stock;
static char *over;
stock.counter = 2;
if ((stock.save = malloc(sizeof(char) * READ_SIZE) + 1) == NULL)
return (NULL);
stock.save = my_strcpy(over, stock.save);
free(over);
while (check_back_n(&stock) == 1)
{
if (my_realloc(&stock) == 1)
return (NULL);
if ((stock.buffer = malloc(sizeof(char) * READ_SIZE) + 1) == NULL)
return (NULL);
if ((stock.read_return = read(fd, stock.buffer, READ_SIZE)) == -1 ||
(stock.read_return == 0))
return (stock.save);
stock.counter = stock.counter + 1;
stock.save = my_strcpy(stock.buffer, stock.save);
free(stock.buffer);
}
if ((over = fill_over(&stock, over)) == NULL)
return (NULL);
return (stock.save);
}
int main()
{
char *s;
int fd;
fd = open("test", O_RDONLY);
while (s = get_next_line(fd))
{
my_putstr(s);
write(1, "\n", 1);
free(s);
}
return (0);
}
结果如下:
*** Error in `./a.out': free(): invalid pointer: 0x0000000002024031 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7283f)[0x7fbb5b3f383f]
/lib64/libc.so.6(+0x780ae)[0x7fbb5b3f90ae]
/lib64/libc.so.6(+0x78db6)[0x7fbb5b3f9db6]
./a.out[0x400a38]
./a.out[0x400ab4]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fbb5b3a2b05]
./a.out[0x4005c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:07 3146955 /home/degana_r/rendu/CProgElem/GetNextLine/CPE_2015_getnextline/a.out
00600000-00601000 r--p 00000000 08:07 3146955 /home/degana_r/rendu/CProgElem/GetNextLine/CPE_2015_getnextline/a.out
00601000-00602000 rw-p 00001000 08:07 3146955 /home/degana_r/rendu/CProgElem/GetNextLine/CPE_2015_getnextline/a.out
02024000-02045000 rw-p 00000000 00:00 0 [heap]
7fbb5b16a000-7fbb5b180000 r-xp 00000000 08:05 157433 /lib64/libgcc_s.so.1
7fbb5b180000-7fbb5b37f000 ---p 00016000 08:05 157433 /lib64/libgcc_s.so.1
7fbb5b37f000-7fbb5b380000 r--p 00015000 08:05 157433 /lib64/libgcc_s.so.1
7fbb5b380000-7fbb5b381000 rw-p 00016000 08:05 157433 /lib64/libgcc_s.so.1
7fbb5b381000-7fbb5b51f000 r-xp 00000000 08:05 147837 /lib64/libc-2.19.so
7fbb5b51f000-7fbb5b71e000 ---p 0019e000 08:05 147837 /lib64/libc-2.19.so
7fbb5b71e000-7fbb5b722000 r--p 0019d000 08:05 147837 /lib64/libc-2.19.so
7fbb5b722000-7fbb5b724000 rw-p 001a1000 08:05 147837 /lib64/libc-2.19.so
7fbb5b724000-7fbb5b728000 rw-p 00000000 00:00 0
7fbb5b728000-7fbb5b748000 r-xp 00000000 08:05 162636 /lib64/ld-2.19.so
7fbb5b91e000-7fbb5b921000 rw-p 00000000 00:00 0
7fbb5b946000-7fbb5b948000 rw-p 00000000 00:00 0
7fbb5b948000-7fbb5b949000 r--p 00020000 08:05 162636 /lib64/ld-2.19.so
7fbb5b949000-7fbb5b94a000 rw-p 00021000 08:05 162636 /lib64/ld-2.19.so
7fbb5b94a000-7fbb5b94b000 rw-p 00000000 00:00 0
7ffc76b9d000-7ffc76bbe000 rw-p 00000000 00:00 0 [stack]
7ffc76be8000-7ffc76bea000 r-xp 00000000 00:00 0 [vdso]
7ffc76bea000-7ffc76bec000 r--p 00000000 00:00 0 [vvar]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted
阅读Logging to a single file from multiple processes后,我用日志模块编写了代码:
from datetime import datetime, timezone
from random import randint
from time import sleep
import multiprocessing
def get_utc_now() -> str:
iso_8601_format = '%Y-%m-%dT%H:%M:%S%z'
return datetime.now(timezone.utc).strftime(iso_8601_format)
def child_process(index: int):
waiting_time = randint(1, 5)
print('{} Child No.{}: Waiting {}s.'.format(get_utc_now(), index, waiting_time))
sleep(waiting_time)
if __name__ == '__main__':
children = {}
multiprocessing.set_start_method('fork')
for i in range(1, 6):
child = multiprocessing.Process(target=child_process, args=(i,))
children[i] = child
child.start()
print('{} Parent: Forking Child No.{} whose pid is {}.'.format(get_utc_now(), i, child.pid))
done_count = 0
while done_count < len(children):
for j, c in children.items():
if c is not None and not c.is_alive():
print('{} Parent: Child No.{} completed.'.format(get_utc_now(), j))
children[j] = None
done_count += 1
print('{} Parent: All done.'.format(get_utc_now()))
结果是:
2016-01-14T01:51:50+0000 Parent: Forking Child No.1 whose pid is 21.
2016-01-14T01:51:50+0000 Parent: Forking Child No.2 whose pid is 22.
2016-01-14T01:51:50+0000 Parent: Forking Child No.3 whose pid is 23.
2016-01-14T01:51:50+0000 Parent: Forking Child No.4 whose pid is 24.
2016-01-14T01:51:50+0000 Child No.2: Waiting 1s.
2016-01-14T01:51:50+0000 Child No.4: Waiting 3s.
2016-01-14T01:51:50+0000 Child No.5: Waiting 4s.
2016-01-14T01:51:50+0000 Child No.1: Waiting 5s.
2016-01-14T01:51:50+0000 Child No.3: Waiting 5s.
2016-01-14T01:51:50+0000 Parent: Forking Child No.5 whose pid is 25.
2016-01-14T01:51:51+0000 Parent: Child No.2 completed.
2016-01-14T01:51:53+0000 Parent: Child No.4 completed.
2016-01-14T01:51:54+0000 Parent: Child No.5 completed.
2016-01-14T01:51:55+0000 Parent: Child No.1 completed.
2016-01-14T01:51:55+0000 Parent: Child No.3 completed.
2016-01-14T01:51:55+0000 Parent: All done.
第二个代码有效,但是儿童的pids与第一个代码不一致。看起来我的第二个代码在循环期间分配了其他进程,我无法弄清楚如何以及为什么。如何改进此代码以解决这种情况?