使用fork方法从多个进程记录到单个文件

时间:2016-01-14 02:38:12

标签: python python-3.x multiprocessing

我正在研究如何从多个进程登录到单个文件并遇到一些问题。

首先,我编写了以下代码而没有记录模块:

#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与第一个代码不一致。看起来我的第二个代码在循环期间分配了其他进程,我无法弄清楚如何以及为什么。如何改进此代码以解决这种情况?

0 个答案:

没有答案