代码之家  ›  专栏  ›  技术社区  ›  Gianni Spear

“状态:系统中打开的文件太多”,打开并锁定

  •  -1
  • Gianni Spear  · 技术社区  · 7 年前

    在linux和C语言中,我有两个函数可以通过5个进程(T1,T2,…,T5)锁定16个文件(MA1,MA2,…,MA16)。使用acquire(…)进程-i锁定文件(如果尚未被其他进程锁定),将0写入1,然后解锁文件。使用释放(…)时,进程将锁定文件,将1写入0,然后解锁文件。当我使用fork()运行时,从open "STATUS: Too many open files in system" . 在Linux中,最大值是1024,但是我的5个进程远不能达到这个极限。

    alessandro@LinuxAle:~$ ulimit -n
    1024
    

    代码是:

    子exe

    #include <string.h>
    #include "accessory.h"
    #include "logfilemanager.h"
    #include "lockmanager.h"
    #include <sys/types.h>
    #include <signal.h>
    
    #define TRAIN_INITIALS "T"
    #define SIZE 256
    
    void next(int step, int *route, int size);
    
    int main(int argc , char *argv[])
    {
    
        char *name[2];
        int *route;
        int fdlog;
        char * logprint;
    
        memset(name, '\0', sizeof(name));
        strcpy(name, TRAIN_INITIALS);
        strcat(name, argv[1]);
        route = get_route(name, "", SIZE);
        print_route(name, route);
    
        fdlog = create_logfile(name, SIZE);
    
    
        for(int i = 1; i < (route[0]+1); i++)
        {
            logprint = update_logfileETC1(fdlog, i, route);
            printf("Train %s: %s", name, logprint);
            fflush(stdout);
            next(i, route, SIZE);
        }
        close(fdlog);
        return 0;
    }
    
    
    void next(int step, int *route, int size) {
    
        char * next_track_name;
        char * actual_track_name;
        char * next_file_path_name;
        char * actual_file_path_name;
        int status;
        int file_exist;
    
        /* acquire */
        next_track_name = get_name(route[step+1]);
        next_file_path_name = get_file_name(next_track_name, "", size);
        file_exist = access(next_file_path_name, F_OK); // check if file exist
        if(file_exist == 0)
        {
            status = acquire(next_file_path_name);
            while(status == -1)
            {
                status = acquire(next_file_path_name);
            }
        }
    
        sleep(3);
    
        /* release */
        actual_track_name = get_name(route[step]);
        actual_file_path_name = get_file_name(actual_track_name, "", size);
        file_exist = access(actual_file_path_name, F_OK); // check if file exist
        if(file_exist == 0)
        {
            status = release(actual_file_path_name);
            while(status == -1)
            {
                status = release(actual_file_path_name);
            }
        }
    }
    

    获取和释放以锁定文件

    include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdlib.h>
    #include <libgen.h>
    
    
    int acquire(char *fname)
    {
    
        char c;
        size_t nbytes;
        int status;
        int fd;
        int close_return;
        struct flock lock; //Create an variable of type struct flock to define the properties of locking
    
        nbytes = sizeof(c);
    
        fd = open(fname, O_RDWR, (mode_t)777);
        if (fd == -1)
        {
            //fd = open(fname, O_RDWR);
            printf("acquire file: %s\n", fname);
            fflush(stdout);
            perror("STATUS");
            exit(1);
        }
    
    
        memset(&lock, 0, sizeof(lock));
        lock.l_type = F_WRLCK;
        lock.l_pid = getpid();
    
        read(fd, &c, nbytes);
    
        if((c - '0') == 1){
            return -1;
        }
    
        /* lock the file */
        status = fcntl(fd, F_SETLK, &lock);
        if(status == -1)
        {
            return -1;
        }
    
        lseek(fd, 0L, SEEK_SET);
        read(fd, &c, nbytes);
    
        if((c - '0') == 0)
        {
            lseek(fd, 0L, SEEK_SET);
            write(fd, "1", nbytes);
        }
        else if ((c - '0') == 1)
        {
            printf("Resource %s is already acquired\n", fname);
            lock.l_type = F_ULOCK;
            if (fcntl(fd, F_SETLKW, &lock) == -1 ) {
                perror("fcntl caused some error: ");
                exit(1);
            }
        }
    
        /* Release the lock */
        lock.l_type = F_ULOCK;
        if (fcntl(fd, F_SETLKW, &lock) == -1 ) {
            perror("fcntl caused some error: ");
            exit(1);
        }
    
        if((close_return = close(fd)) < 0)
        {
            perror("close");
            exit(1);
        }
    
        return 0;
    }
    
    
    
    int release(char *fname)
    {
        char c;
        size_t nbytes;
        int status;
        int fd;
        int close_return;
        struct flock lock; //Create an variable of type struct flock to define the properties of locking
    
        nbytes = sizeof(c);
    
        fd = open(fname, O_RDWR, (mode_t)777);
        if (fd == -1)
        {
            //fd = open(fname, O_RDWR);
            printf("release file: %s\n", fname);
            fflush(stdout);
            perror("STATUS");
            exit(1);
        }
    
        memset(&lock, 0, sizeof(lock));
        lock.l_type = F_WRLCK;
        lock.l_pid = getpid();
    
        /* lock the file */
        status = fcntl(fd, F_SETLK, &lock);
        if(status == -1)
        {
            return -1;
        }
    
        lseek(fd, 0L, SEEK_SET);
        write(fd, "0", nbytes);
    
        /* Release the lock */
        lock.l_type = F_ULOCK;
        if (fcntl(fd, F_SETLKW, &lock) == -1 ) {
            perror("fcntl caused some error: ");
            exit(EXIT_FAILURE);
        }
    
        if((close_return = close(fd)) < 0)
        {
            perror("close");
            exit(1);
        }
    
        return 0;
    }
    

    叉子的主要部分是:

    #include <stdio.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include "accessory.h"
    #include <sys/types.h>
    #include <signal.h>
    
    
    #define NUMBER_TRACKS 16
    #define NUMBER_STATIONS 8
    #define NUMBER_TRAINS 5
    
    #define TRACKS_INITIALS "MA"
    #define STATION_INITIALS "S"
    #define SIZE 256
    #define CHILDETCONE "childETCone"
    
    
    
    
    int main(int argc , char *argv[])
    {
    
        pid_t pid;
    
        char track_name[2];
        char track_number[2];
        int execl_return;
    
        char index[2];
        char * execl_path_name;
    
    
    
        /* create the MAx file initialized to zero */
        for(int i = 1; i < (NUMBER_TRACKS+1); i++)
        {
            memset(track_name, '\0', sizeof(track_name));
            memset(track_number, '\0', sizeof(track_number));
            strcpy(track_name, TRACKS_INITIALS);
            sprintf(track_number, "%d", i);
            strcat(track_name, track_number);
            create_track_file(track_name, "", SIZE);
        }
    
        execl_path_name = get_file_name(CHILDETCONE, "", SIZE);
        printf("path %p\n", execl_path_name);
    
    
        for(int i = 0; i < NUMBER_TRAINS; i++)
        {
            pid = fork();
    
            if (pid < 0)
            {
                perror("fork");
                exit(1);
            }
            if (pid == 0) //child
            {
    
                sprintf(index, "%d", i+1);
                execl_return = execl(execl_path_name, CHILDETCONE, index, NULL);
                if(execl_return == -1)
                {
                    perror("execl");
                    exit(1);
                }
                exit(0);
            }
    
        }
    
        for (int i = 0; i < NUMBER_TRAINS; i++)
        {
            wait(NULL);
        }
    
        return 0;
    

    结果是:

    Route of train T5: [S5, MA4, MA3, MA2, MA1, S1]
    Train T5: [Attuale: S5], [Next: MA4], 7 Agosto 2018 0:35:31
    Route of train T4: [S6, MA8, MA3, MA2, MA1, S1]
    Train T4: [Attuale: S6], [Next: MA8], 7 Agosto 2018 0:35:31
    Route of train T3: [S4, MA14, MA15, MA16, MA12, S8]
    Train T3: [Attuale: S4], [Next: MA14], 7 Agosto 2018 0:35:31
    Route of train T2: [S3, MA9, MA10, MA11, MA12, S8]
    Train T2: [Attuale: S3], [Next: MA9], 7 Agosto 2018 0:35:31
    Route of train T1: [S2, MA5, MA6, MA7, MA3, MA8, S6]
    Train T1: [Attuale: S2], [Next: MA5], 7 Agosto 2018 0:35:31
    Train T4: [Attuale: MA8], [Next: MA3], 7 Agosto 2018 0:35:34
    Train T5: [Attuale: MA4], [Next: MA3], 7 Agosto 2018 0:35:34
    Train T3: [Attuale: MA14], [Next: MA15], 7 Agosto 2018 0:35:34
    Train T2: [Attuale: MA9], [Next: MA10], 7 Agosto 2018 0:35:34
    Train T1: [Attuale: MA5], [Next: MA6], 7 Agosto 2018 0:35:34
    acquire file: /home/alessandro/CLionProjects/ETC1/cmake-build-debug/MA3
    STATUS: Too many open files in system
    Train T2: [Attuale: MA10], [Next: MA11], 7 Agosto 2018 0:35:37
    Train T1: [Attuale: MA6], [Next: MA7], 7 Agosto 2018 0:35:37
    Train T4: [Attuale: MA3], [Next: MA2], 7 Agosto 2018 0:35:37
    Train T3: [Attuale: MA15], [Next: MA16], 7 Agosto 2018 0:35:37
    Train T3: [Attuale: MA16], [Next: MA12], 7 Agosto 2018 0:35:40
    Train T4: [Attuale: MA2], [Next: MA1], 7 Agosto 2018 0:35:40
    Train T2: [Attuale: MA11], [Next: MA12], 7 Agosto 2018 0:35:40
    Train T1: [Attuale: MA7], [Next: MA3], 7 Agosto 2018 0:35:40
    acquire file: /home/alessandro/CLionProjects/ETC1/cmake-build-debug/MA12
    STATUS: Too many open files in system
    Train T3: [Attuale: MA12], [Next: S8], 7 Agosto 2018 0:35:43
    Train T4: [Attuale: MA1], [Next: S1], 7 Agosto 2018 0:35:43
    Train T1: [Attuale: MA3], [Next: MA8], 7 Agosto 2018 0:35:43
    Train T3: [Attuale: S8], [Next: --], 7 Agosto 2018 0:35:46
    Train T4: [Attuale: S1], [Next: --], 7 Agosto 2018 0:35:46
    Train T1: [Attuale: MA8], [Next: S6], 7 Agosto 2018 0:35:46
    Train T1: [Attuale: S6], [Next: --], 7 Agosto 2018 0:35:49
    
    Process finished with exit code 0
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Craig Estey    7 年前

    acquire ,您可以:

    if((c - '0') == 1){
        return -1;
    }
    
    /* lock the file */
    status = fcntl(fd, F_SETLK, &lock);
    if(status == -1)
    {
        return -1;
    }
    

    如果其中任何一个 if 语句返回,您将从函数返回 没有 关闭打开的文件描述符。

    注: 因为你没有发布你的整个子程序代码(即 execle ),很难说这会产生什么样的影响,但这是高度怀疑。


    更新:

    我伪造了儿童密码

    好吧,这显然证实了错误。两者 获得 release 被称为 next 如果 任何一个 一次返回-1:

    1. 这意味着您将在以后的每次调用中开始使用文件描述符。
    2. 你可能会得到一个无限循环,因为 下一个 如果收到-1返回,将再次[并再次]调用它们

    只需添加:

    close(fd);
    

    之前 你的 return -1 以上陈述。

    请注意 释放 也有类似的 if (status == -1) return -1 问题。