日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pipe读写前设置O_NOATIME

發布時間:2025/3/21 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pipe读写前设置O_NOATIME 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux下的pipe使用非常廣泛, shell本身就大量用pipe來粘合生產者和消費者的. 我們的服務器程序通常會用pipe來做線程間的ipc通訊. 由于unix下的任何東西都是文件,只要是文件,在讀取的時候,,就會設置last access time, 所以pipe也不例外., 但是這個時間對我們沒有意義 如果pipe使用的非常頻繁的時候會碰到由于設置訪問時間導致的性能問題. 這個開銷遠比pipe讀寫的本身開銷大. 相比文件讀寫的開銷, atime微不足道,但是對pipe來講就不同了.
這個事情是上次和多隆同學在把玩他的網絡框架的時候,無意發現的.


我們來分析下pipe的這部分代碼:


//pipe.c:L349
static ssize_t
pipe_read(struct kiocb *iocb, const struct iovec *_iov,
? ? ? ? ? ? ? ?unsigned long nr_segs, loff_t pos)
{
...
? ?if (ret > 0)
? ? ? ? file_accessed(filp);
? ? return ret;
}
我們可以看到在pipe讀的時候要設置 file_accessed時間的,接著:


//fs.h:L1761
extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
static inline void file_accessed(struct file *file)
{
? ? ? ? if (!(file->f_flags & O_NOATIME))
? ? ? ? ? ? ? ? touch_atime(file->f_path.mnt, file->f_path.dentry);
}
如果文件沒設置 O_NOATIME就真正動手設置atime,接著:


//inode.c:L1493
void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
{
? ? ? ? struct inode *inode = dentry->d_inode;
? ? ? ? struct timespec now;
?
? ? ? ? if (inode->i_flags & S_NOATIME)
? ? ? ? ? ? ? ? return;
? ? ? ? if (IS_NOATIME(inode))
? ? ? ? ? ? ? ? return;
? ? ? ? if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
? ? ? ? ? ? ? ? return;
?
? ? ? ? if (mnt->mnt_flags & MNT_NOATIME)
? ? ? ? ? ? ? ? return;
? ? ? ? if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
? ? ? ? ? ? ? ? return;
?
? ? ? ? now = current_fs_time(inode->i_sb);
?
? ? ? ? if (!relatime_need_update(mnt, inode, now))
? ? ? ? ? ? ? ? return;
?
? ? ? ? if (timespec_equal(&inode->i_atime, &now))
? ? ? ? ? ? ? ? return;
?
? ? ? ? if (mnt_want_write(mnt))
? ? ? ? ? ? ? ? return;
?
? ? ? ? inode->i_atime = now;
? ? ? ? mark_inode_dirty_sync(inode);
? ? ? ? mnt_drop_write(mnt);
}
我們可以看出上面的流程還是比較復雜的,開銷也很大.
我們來演示下:

Linux下pipe使用注意事項

https://blog.csdn.net/xiaofei0859/article/details/50601180


$ cat > pipe_test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/unistd.h>
?
static int fds[2];
static pthread_t rp;
?
static void *rp_entry(void *arg) {
? char c[1];
? while (1 == read(fds[0], c, 1)) {
? ? if (*c == 'Q') break;
? }
? fprintf(stderr, "pipe read ok\n");
? return NULL;
}
?
int main(int argc, char *argv[]) {
? long i, n;
? int rc;
? if (argc < 2) {
? ? fprintf(stderr, "usage: pipe_test NNNNNN\n");
? ? return -1;
? }
? n = atol(argv[1]);
? pipe(fds);
? //fcntl(fds[0], F_SETFL, O_NOATIME);
? pthread_create(&rp, NULL, rp_entry, NULL);
? fprintf(stderr, "pipe write %ld...", n);
? for (i = 0; i < n; i++) {
? ? write(fds[1], "A", 1);
? }
? write(fds[1], "Q", 1);
? fprintf(stderr, "ok\n");
? pthread_join(rp, NULL);
? close(fds[0]);
? close(fds[1]);
? return 0;
}
CTRL+D
$ gcc -D_GNU_SOURCE pipe_test.c -lpthread
$ sudo opcontrol --setup --vmlinux=/usr/lib/debug/lib/modules/2.6.18-164.el5/vmlinux
$ sudo opcontrol --init && sudo opcontrol --reset && sudo opcontrol --start
$ ./a.out 10000000
pipe write 10000000...ok
pipe read ok
$ sudo opcontrol --shutdown
$ opreport -l|less ? ? ? ? ? ?
samples ?% ? ? ? ?app name ? ? ? ? ? ? ? ? symbol name
378654 ? 92.7742 ?vmlinux ? ? ? ? ? ? ? ? ?.text.acpi_processor_idle
12978 ? ? 3.1797 ?vmlinux ? ? ? ? ? ? ? ? ?current_fs_time
2530 ? ? ?0.6199 ?vmlinux ? ? ? ? ? ? ? ? ?thread_return
2345 ? ? ?0.5745 ?vmlinux ? ? ? ? ? ? ? ? ?touch_atime
2253 ? ? ?0.5520 ?vmlinux ? ? ? ? ? ? ? ? ?.text.acpi_safe_halt
1597 ? ? ?0.3913 ?vmlinux ? ? ? ? ? ? ? ? ?timespec_trunc
1368 ? ? ?0.3352 ?vmlinux ? ? ? ? ? ? ? ? ?file_update_time
1253 ? ? ?0.3070 ?vmlinux ? ? ? ? ? ? ? ? ?__mark_inode_dirty
901 ? ? ? 0.2208 ?vmlinux ? ? ? ? ? ? ? ? ?pipe_writev
768 ? ? ? 0.1882 ?vmlinux ? ? ? ? ? ? ? ? ?__mutex_lock_slowpath
763 ? ? ? 0.1869 ?vmlinux ? ? ? ? ? ? ? ? ?try_to_wake_up
270 ? ? ? 0.0662 ?vmlinux ? ? ? ? ? ? ? ? ?copy_user_generic_unrolled
254 ? ? ? 0.0622 ?vmlinux ? ? ? ? ? ? ? ? ?acpi_set_register
254 ? ? ? 0.0622 ?vmlinux ? ? ? ? ? ? ? ? ?system_call
233 ? ? ? 0.0571 ?vmlinux ? ? ? ? ? ? ? ? ?pipe_readv
188 ? ? ? 0.0461 ?vmlinux ? ? ? ? ? ? ? ? ?dnotify_parent
167 ? ? ? 0.0409 ?vmlinux ? ? ? ? ? ? ? ? ?mutex_unlock
...
我們可以看到touch_atime的開銷很大,遠比pipe的讀寫大.
這次把這行注釋去掉: fcntl(fds[0], F_SETFL, O_NOATIME); 指示pipe在讀的時候不更新atime,看下效果:


view sourceprint?
$ opreport -l|less
samples ?% ? ? ? ?app name ? ? ? ? ? ? ? ? symbol name
599018 ? 95.2466 ?vmlinux ? ? ? ? ? ? ? ? ?.text.acpi_processor_idle
4140 ? ? ?0.6583 ?vmlinux ? ? ? ? ? ? ? ? ?.text.acpi_safe_halt
3281 ? ? ?0.5217 ?vmlinux ? ? ? ? ? ? ? ? ?thread_return
2812 ? ? ?0.4471 ?vmlinux ? ? ? ? ? ? ? ? ?current_fs_time
2615 ? ? ?0.4158 ?vmlinux ? ? ? ? ? ? ? ? ?file_update_time
1790 ? ? ?0.2846 ?vmlinux ? ? ? ? ? ? ? ? ?__mutex_lock_slowpath
1657 ? ? ?0.2635 ?vmlinux ? ? ? ? ? ? ? ? ?timespec_trunc
1341 ? ? ?0.2132 ?vmlinux ? ? ? ? ? ? ? ? ?try_to_wake_up
1281 ? ? ?0.2037 ?vmlinux ? ? ? ? ? ? ? ? ?mutex_unlock
1080 ? ? ?0.1717 ?vmlinux ? ? ? ? ? ? ? ? ?mutex_lock
1001 ? ? ?0.1592 ?vmlinux ? ? ? ? ? ? ? ? ?pipe_readv
925 ? ? ? 0.1471 ?vmlinux ? ? ? ? ? ? ? ? ?pipe_writev
這下看不到touch_atime了,開銷省了,對于高性能服務器是很重要的.
小結: 細節很重要,記得開文件open的時候設置O_NOATIME或者用fcntl搞定它.
祝玩得開心!

總結

以上是生活随笔為你收集整理的pipe读写前设置O_NOATIME的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。