¿Cómo bloqueo archivos usando fopen()?

6 minutos de lectura

avatar de usuario
emir

Me pregunto si hay alguna forma de bloquear y desbloquear un archivo en Linux cuando abro un archivo usando fopen (no open)?

Basado en la pregunta de desbordamiento de pila C fopen vs abierto, fopen se prefiere sobre open.

¿Cómo puedo implementar mi propio bloqueo de archivos (si es posible) creando y eliminando archivos de bloqueo?

avatar de usuario
R.. GitHub DEJAR DE AYUDAR A ICE

Estoy totalmente en desacuerdo con la afirmación de que fopen se prefiere sobre open. es imposible de usar fopen de forma segura al escribir un archivo en un directorio en el que otros usuarios pueden escribir debido a vulnerabilidades de enlaces simbólicos/condiciones de carrera, ya que no hay O_EXCL opción. Si necesita usar stdio en sistemas POSIX, es mejor usar open y fdopen en lugar de llamar fopen directamente.

Ahora, en cuanto al bloqueo, depende de lo que quieras hacer. POSIX no tiene un bloqueo obligatorio como Windows, pero si solo quiere asegurarse de que está trabajando con un archivo nuevo y no golpeando un archivo existente o siguiendo un enlace simbólico, use el O_EXCL y O_NOFOLLOW opciones, según corresponda. Si desea realizar un bloqueo cooperativo más allá de la apertura inicial, utilice fcntl Cerraduras.

  • No puedo hacer una edición de 1 carácter, ¿te importaría corregir ese error tipográfico, es un poco confuso cerca ... rather than calling fdopen directly ... – Asumo que te referías fopen

    – MickLH

    22 mayo 2015 a las 17:37

avatar de usuario
Robᵩ

En Linux, si necesita un descriptor de archivo (por ejemplo, para pasar a una primitiva de bloqueo de archivos), puede usar fileno(FILE*) para recuperarlo. Después de recuperar el descriptor de archivo, puede usarlo como si lo hubiera devuelto open.

Por ejemplo, en lugar de

int fd = open("myfile.txt", flags);
int result = flock(fd, LOCK_SH);

igualmente podrías hacer esto:

FILE* f = fopen("myfile.txt", "r");
int result = flock(fileno(f)), LOCK_SH);

Tenga en cuenta que fileno se define en el estándar POSIX, pero no en los estándares C o C++.

En cuanto a su segunda pregunta, Linux open() página man tiene esto que decir:

La solución para realizar el bloqueo de archivos atómicos usando un archivo de bloqueo es crear un archivo único en el mismo sistema de archivos (por ejemplo, incorporando el nombre de host y el pid), use enlace(2) para hacer un enlace al archivo de bloqueo. Si link() devuelve 0, el bloqueo es exitoso. De lo contrario, utilice estadística(2) en el archivo único para verificar si su recuento de enlaces ha aumentado a 2, en cuyo caso el bloqueo también es exitoso.

  • @EdHeal: las transmisiones tienen búferes, lo que significa que deberá tener cuidado de vaciar en los momentos apropiados.

    – derobert

    27 de septiembre de 2011 a las 17:42

  • @derobert: el lavado está bien para escribir. Pero considere leer parte de un archivo, parte está en el búfer, parte no está en el búfer

    – Ed Heal

    27 de septiembre de 2011 a las 17:49

  • @EdHeal: Bueno, obviamente, también se debe vaciar el búfer de entrada. No es difícil, teniendo en cuenta fflush lo hace…

    – derobert

    27 de septiembre de 2011 a las 17:53

  • @derobert, es decir, el mecanismo de flujos agrega una sobrecarga adicional. mejor usar read y write llamadas al sistema en primer lugar.

    – Ed Heal

    27 de septiembre de 2011 a las 17:54

  • @EdHeal: Depende de lo que estés haciendo. Si va a obtener un bloqueo, haga mucho IO, luego suelte el bloqueo, el lavado del búfer no es tan malo. Pero sí, si está constantemente descargando búferes, entonces debería usar uno de los mejores métodos (lectura/escritura o mmap).

    – derobert

    27/09/2011 a las 17:57

Los archivos se pueden bloquear usando flock(). Su sintaxis es

 #include <sys/file.h>
 #define   LOCK_SH   1    /* shared lock */
 #define   LOCK_EX   2    /* exclusive lock */
 #define   LOCK_NB   4    /* don't block when locking */
 #define   LOCK_UN   8    /* unlock */

int flock(int fd, int operation);

El primer archivo se abre usando fopen() o open(). Entonces este archivo abierto se bloquea usando flock() como se indica a continuación

int fd = open("test.txt","r");
int lock = flock(fd, LOCK_SH);  // Lock the file . . .
// . . . .
// Locked file in use 
// . . . .
int release = flock(fd, LOCK_UN);  // Unlock the file . . .

  • open() no acepta un argumento de cadena para el modo. Eso es fopen(). Pero, de nuevo, fopen no devuelve un int, sino un ARCHIVO*. Edite para aclarar exactamente lo que quería usar

    – kyriakosSt

    3 de abril de 2019 a las 14:22

avatar de usuario
Shoaib Ahmed

Tenga en cuenta que en el siguiente código fopen fallará (y devolverá NULL) si el archivo de bloqueo /var/lock/my.lock no existe

FILE* f = fopen("/var/lock/my.lock", "r");
int result = flock(fileno(f)), LOCK_SH);

Utilizar fopen con w+ si necesita que se cree el archivo de bloqueo si no existe.

FILE* f = fopen("/var/lock/my.lock", "w+");
int result = flock(fileno(f)), LOCK_SH);

Si desea implementar su propio bloqueo de forma sencilla, sugiero la respuesta de Rob de usar flock. Si desea implementarlo de una manera compleja, como alta disponibilidad, puede probar algo como usar un hilo para tocar un archivo a intervalos regulares. Todos los demás programas que deseen bloquear el archivo también deben verificar el archivo para ver si su tiempo de actualización se ha actualizado en otro intervalo fijo, pero más grande (la parte más grande es importante). Esto probablemente sea excesivo para la mayoría de las aplicaciones, pero maneja cosas como bloqueos, bloqueos, etc. mucho mejor que flock.

avatar de usuario
Pedro Mortensen

Hay otra manera con abierto() función, pero no estoy seguro acerca de este llamado archivo bloqueado. Estoy usando permisos de archivo para abrir un archivo.

El código está aquí:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#define FILE_NAME "hello.txt"

int main()
{
    int fd;

    fd = open(FILE_NAME, O_CREAT, S_IRWXU);

    // Error checking
    if(fd == -1){
        perror("[error]\n");
    }
    else{
        printf("[file is opened]\n");
    }

    return 0;
}

Usé una bandera para permisos (tercer argumento). Esta bandera otorga permisos de lectura, escritura y ejecución al usuario.

$ls -alh

total 24K
drwxrwxr-x  2 arien arien 4.0K Dec 28 20:56 .
drwxrwxr-x 18 arien arien 4.0K Dec 27 22:20 ..
-rwxrwxr-x  1 arien arien 8.5K Dec 28 20:56 fopen
-rw-rw-r--  1 arien arien  290 Dec 28 20:56 fopen.c
-rwx------  1 arien arien    0 Dec 28 20:55 hello.txt

Un pequeño consejo: si está utilizando Ubuntu o Debian, puede ver la descripción de las funciones con man [function_name] páginas man de la función open().

avatar de usuario
Asif Bahréinwala

El siguiente código no me permite bloquear el archivo usando lockf, aunque flock funciona bien

    #include <iostream>
    #include <unistd.h>
    #include<thread>
    #include <vector>
    #include <sys/file.h>
    #include <fcntl.h>
    #include <string.h>

using namespace std;

void append()
{
    FILE *fp=fopen("a.txt","a");
    if(fp)
    {
        cout<<lockf(fileno(fp),F_LOCK,0)<<endl;

        //flock(fileno(fp), LOCK_EX);

        fprintf(fp,"abcdefghijklmnopqrstuvwxyz\n");fflush(fp);
        sleep(1);
        fprintf(fp,"^$^&%&*&^&*(*)_*)_()_*&***&(\n");fflush(fp);

        fclose(fp);
    }
    else {
        printf("null\n");
    }
}


int main()
{
    fclose(fopen("a.txt","w"));
    //return 0;
    vector<thread*> v;
    //#pragma omp parallel for
    for(int i=0;i<1000;++i)
    {
        v.push_back(new thread(append));

        //append();
    }

    for(auto y:v)
    {
        y->join();
        delete y;
    }

    return 0;
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad