2015-05-21 18 views
8

Wziąłem bezpiecznik hello.c i zmodyfikowałem spód, aby pokazać, o czym mówię. W mojej aplikacji muszę robić rzeczy po tym, jak mój bezpiecznik FS jest dostępny. Potrzebuję również innego wątku dla IPC i utrzymywania pewnych rzeczy na bieżąco. Ponieważ wydaje się, że fuse_main nie powrócił, rzuciłem go w swój własny wątek.Dlaczego FUSE wydaje się blokować wszystkie wątki?

Po skomentowaniu fuse_main na konsoli widać wydrukowane A i B. Jednak jeśli nie komentuję fuse_main (która jest w innym wątku), tylko A jest drukowane. Jak do cholery jest bezpiecznik, który zatrzymuje mój główny wątek i jak uruchomić kod po tym, jak FUSE robi swoje rzeczy?

#define FUSE_USE_VERSION 26 

#include <fuse.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <fcntl.h> 

static const char *hello_str = "Hello World!\n"; 
static const char *hello_path = "/hello"; 

static int hello_getattr(const char *path, struct stat *stbuf) 
{ 
    int res = 0; 

    memset(stbuf, 0, sizeof(struct stat)); 
    if (strcmp(path, "/") == 0) { 
     stbuf->st_mode = S_IFDIR | 0755; 
     stbuf->st_nlink = 2; 
    } else if (strcmp(path, hello_path) == 0) { 
     stbuf->st_mode = S_IFREG | 0444; 
     stbuf->st_nlink = 1; 
     stbuf->st_size = strlen(hello_str); 
    } else 
     res = -ENOENT; 

    return res; 
} 

static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 
      off_t offset, struct fuse_file_info *fi) 
{ 
    (void) offset; 
    (void) fi; 

    if (strcmp(path, "/") != 0) 
     return -ENOENT; 

    filler(buf, ".", NULL, 0); 
    filler(buf, "..", NULL, 0); 
    filler(buf, hello_path + 1, NULL, 0); 

    return 0; 
} 

static int hello_open(const char *path, struct fuse_file_info *fi) 
{ 
    if (strcmp(path, hello_path) != 0) 
     return -ENOENT; 

    if ((fi->flags & 3) != O_RDONLY) 
     return -EACCES; 

    return 0; 
} 

static int hello_read(const char *path, char *buf, size_t size, off_t offset, 
       struct fuse_file_info *fi) 
{ 
    size_t len; 
    (void) fi; 
    if(strcmp(path, hello_path) != 0) 
     return -ENOENT; 

    len = strlen(hello_str); 
    if (offset < len) { 
     if (offset + size > len) 
      size = len - offset; 
     memcpy(buf, hello_str + offset, size); 
    } else 
     size = 0; 

    return size; 
} 

static struct fuse_operations hello_oper; 
//modification starts below this line 
#include<thread> 
#include<unistd.h> 
int main(int argc, char *argv[]) 
{ 
    std::thread t([&]{ 
     hello_oper.getattr = hello_getattr; 
     hello_oper.readdir = hello_readdir; 
     hello_oper.open  = hello_open; 
     hello_oper.read  = hello_read; 

     return fuse_main(argc, argv, &hello_oper, NULL); 
    }); 
    printf("A\n"); 
    sleep(5); 
    printf("B\n"); 
    t.join(); 
} 

Odpowiedz

8

fuse_main daemonizes, tj wzywa fork() i wzywa _exit(0) w procesie macierzystym, więc wychodzi procesowe, stąd widać tylko wydruk A.

Jeśli dasz opcję -f w ./hello -f /tmp/fusefuse_main nie nazywają _exit ale pozostaje przy życiu na pierwszym planie i oba A i B widać.

pewno potrzebny jest sposób, aby zakończyć wątek fuse_main wdzięcznie, gdy program chce wyjść:

//modification starts below this line 
#include<thread> 
#include<unistd.h> 
#include <signal.h> 
#include <sys/syscall.h> 

int main(int argc, char *argv[]) 
{ 
    pid_t tid; 
    std::thread t([&]{ 
     hello_oper.getattr = hello_getattr; 
     hello_oper.readdir = hello_readdir; 
     hello_oper.open  = hello_open; 
     hello_oper.read  = hello_read; 

     tid = syscall(SYS_gettid); 
     return fuse_main(argc, argv, &hello_oper, NULL); 
    }); 
    printf("A\n"); 
    sleep(5); 
    printf("B\n"); 
    kill(tid, SIGTERM); 
    t.join(); 
} 

Opcje hello:

general options: 
    -o opt,[opt...]  mount options 
    -h --help   print help 
    -V --version   print version 

FUSE options: 
    -d -o debug   enable debug output (implies -f) 
    -f      foreground operation 
    -s      disable multi-threaded operation 
[...] 
+0

Dzięki. Po tym, jak wszystko będzie działać, przyjmuję odpowiedź. Gdzie i tak znalazłeś opcję '-f'? Chciałbym zobaczyć wszystkie opcje –

+0

Znalazłem je, gdy sprawdzałem kod źródłowy bezpiecznika, aby zobaczyć, co robi 'fuse_main'. Ale widziałem, że mogą po prostu wydrukować z './hello --help'. – 4566976

4

Z tego co czytałem w dokumentacji tutaj http://fuse.sourceforge.net/doxygen/hello_8c.html na korzystanie z programu hello.c, to mówi, że program wychodzi i znika w tle, czyli charakter fuse_main API. Dlaczego nie spróbować, wychodząc z tego kodu http://fuse.sourceforge.net/doxygen/hello__ll_8c.html z ich opisem, unlike hello.c this example will stay in the foreground. it also replaced the convenience function fuse_main(..) with a more low level approach. ten sposób w wierszu,

err = fuse_session_loop(se);

w głównej funkcji masz kontrolę do Uzupełnienia i robić inne rzeczy, które chcesz robić.

Ponadto istnieje C++ realizacja zapalnika, https://code.google.com/p/fusekit/

Nadzieja to pomaga.

+1

Jeśli 'fuse_main()' widelce funkcyjnych wtedy, tak, twoje nici znikną, gdy rozwidlanie zachowuje wykonanie tylko rozwidlonej nitki. – wilx

Powiązane problemy