目前看以前的代码想到一个问题,unlink rm 区别 和和 close 的区别!
主要场景是 想使用 文件大内核锁进行多进程互斥!
多进程中使用 文件锁互斥方式如下:
mtx->fd = open_file(file_name); mtx->name = file_name; fork()
也就是fork 后 进程都用这个文件的fd 然后根据文件fd 的文件锁进行互斥访问!!
当然 多进程 访问 fd 的文件锁时 可以根据需要 设置不同的获取锁规则!比如 可以实现类似于spin_lock try_lock的动作
trylock_fd(fd_t fd) { struct flock fl; memzero(&fl, sizeof(struct flock)); //这个文件锁并不用于锁文件中的内容,填充为0 fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; /* 使用F_SETLK lock_fd方法获取互斥锁成功时会返回0,否则返回的其实是errno错误码,而这个错误码为NGX- EAGAIN或者NGX EACCESS时 表示当前没有拿到互斥锁,否则可以认为fcntl执行错误。 */ if (fcntl(fd, F_SETLK, &fl) == -1) { return ngx_errno; } return 0; } /* lock_fd方法将会阻塞进程的执行 */ lock_fd(fd_t fd) { struct flock fl; memzero(&fl, sizeof(struct flock)); //F_SETLKW 会导致进程睡眠 fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; //如果返回-1,则表示fcntl执行错误。一旦返回0,表示成功地拿到了锁 if (fcntl(fd, F_SETLKW, &fl) == -1) { return ngx_errno; } return 0; }
参考文件:https://man7.org/linux/man-pages/man2/fcntl.2.html
F_SETLK (struct flock *) Acquire a lock (when l_type is F_RDLCK or F_WRLCK) or release a lock (when l_type is F_UNLCK) on the bytes specified by the l_whence, l_start, and l_len fields of lock. If a conflicting lock is held by another process, this call returns -1 and sets errno to EACCES or EAGAIN. (The error returned in this case differs across implementations, so POSIX requires a portable application to check for both errors.) F_SETLKW (struct flock *) As for F_SETLK, but if a conflicting lock is held on the file, then wait for that lock to be released. If a signal is caught while waiting, then the call is interrupted and (after the signal handler has returned) returns immediately (with return value -1 and errno set to EINTR; see signal(7)).
man7 中可以看到解释!!
由于此时只是需要多进程的互斥 所以一般是 open fd 后 就回调用unlink 删除此文件!!
对于 守护进程中使用 文件锁 来保证 单一进程拉起时, 此时不需要删除文件!!
对于 unlink 和 rm close 关系
下面是来之网上的一段话!!认为是对的 !!
每一个文件,都可以通过一个struct stat的结构体来获得文件信息,其中一个成员st_nlink代表文件的链接数。当通过shell的touch命令或者在程序中open一个带有O_CREAT的不存在的文件时,文件的链接数为1。
通常open一个已存在的文件不会影响文件的链接数。open的作用只是使调用进程与文件之间建立一种访问关系,即open之后返回fd,调用进程可以通过fd来read 、write 、 ftruncate等等一系列对文件的操作。
close()就是消除这种调用进程与文件之间的访问关系。自然,不会影响文件的链接数。在调用close时,内核会检查打开该文件的进程数,如果此数为0,进一步检查文件的链接数,如果这个数也为0,那么就删除文件内容!! link函数创建一个新目录项,并且增加一个链接数。 unlink函数删除目录项,并且减少一个链接数。如果链接数达到0并且没有任何进程打开该文件,该文件内容才被真正删除。 如果在unlilnk之前没有close,那么依旧可以访问文件内容。
对于 rm 和unlink的区别!
见这篇文章:https://unix.stackexchange.com/questions/151951/what-is-the-difference-between-rm-and-unlink
POSIX specifies that the unlink
utility calls the C library unlink
function and nothing else. It takes no option. If you pass a valid path name to something which isn't a directory, and if you have write permissions to the directory where that object lives, then unlink
will remove it.
rm
is a traditional Unix command which has a bit of other functionality, and isn't quite a superset of unlink
(see below).
Firstly, rm
performs safety checks. If you try to rm
an object to which you don't have write permissions (which are irrelevant to your ability to remove it: the containing directory's permissions are!) rm
nevertheless refuses unless -f
is specified. rm
normally complains if the file doesn't exist, as does unlink
; however with -f
, rm
does not complain. This is often exploited in Makefiles (clean: @rm -f $(OBJS) ...
) so make clean
doesn't fail when there is nothing to remove.
Secondly, rm
has the -i
option for interactively confirming the delete.
Thirdly, rm
has -r
for recursively removing a directory, which is something that unlink
isn't required to do, since the C library function doesn't do that.
The unlink
utility isn't exactly a stripped-down rm
. It performs a subset of what rm
does, but it has semantics which is a combination of rm
with -f
and rm without -f
.