背景:
我正在嘗試撰寫一個同時記錄 JSONS 的小腳本,如果檔案大小很小,則一切正常。但是當檔案很大時,行程開始相互覆寫。這篇 SO 帖子有助于指出正確的方向:PIPE_BUFF。Windows 似乎將其設定為 1024,在 linux 上更大PIPE_BUFF 有多大?
PS:我在 WSL2 Ubuntu 20.04
問題
我嘗試使用Fcntl 常量 F_SETPIPE_SZ設定 PIPE_BUFF 值,但是我沒有成功:
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Data::Dumper qw(Dumper);
use File::Basename qw(basename dirname);
use File::Spec qw(catfile file_name_is_absolute catdir);
use feature qw(say current_sub);
use Cwd qw(abs_path);
use lib dirname(abs_path $0);
use Fcntl qw(F_SETPIPE_SZ F_GETPIPE_SZ F_GETFL F_GETFD F_SETFL O_NONBLOCK O_WRONLY O_APPEND O_CREAT O_RDWR F_DUPFD F_SETOWN F_GETOWN);
open(my $fileH,">", File::Spec -> catfile(dirname(__FILE__), "blabla.txt"));
#does F_GETFD work?
my $val = fcntl($fileH, F_GETFD, 0);
say $val; #outputs 1, works
#does F_GETFL work?
my $val2 = fcntl($fileH, F_GETFL, 0);
say $val2; #outputs 32769, works
#does F_GETOWN work?
my $val3 = fcntl($fileH, F_GETOWN, 0);
say $val3; #outputs 0 but true, so it works too.
my $pid = $$;#process id
#does F_SETOWN work?
my $val4 = fcntl($fileH, F_SETOWN, $pid) or die("error: $!");;
say $val4; #outputs 0 but true
#does getting pipe buffer work?
my $val5 = fcntl($fileH, F_GETPIPE_SZ, 0) or die("error: $!"); #"Bad file descriptor"
say $val5; #Use of uninitialized..so $val5 is undef, did not work
#does setting pipe buffer work?
my $val6 = fcntl($fileH, F_SETPIPE_SZ, 1000 * 1000) or die("error: $!"); #"Bad file descriptor"
say $val6; #undef
像 F_GETFD 或 F_GETFL 這樣的幾個常量可以作業,所以我猜 Fcntl 運行正常。
但是 F_SETPIPE_SZ 和其他一些似乎根本不起作用。傳遞fcntl fileno($fileH)而不是$fileH導致“未打開的檔案句柄”錯誤,因此它也不會改變任何東西。
What is the underlying reason for this?
uj5u.com熱心網友回復:
顧名思義, Linuxfcntl()標志F_GETPIPE_SZ和F_SETPIPE_SZ特定于管道。您正在嘗試將它們與常規檔案一起使用,因此會失敗。
為了清楚起見:
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;
use Fcntl qw/F_GETPIPE_SZ/;
open my $file, ">", "/tmp/foo.txt" or die "Unable to open /tmp/foo.txt: $!\n";
pipe my $reader, my $writer or die "Unable to create pipe: $!\n";
if (my $size = fcntl($file, F_GETPIPE_SZ, 0)) {
say "filehandle size: $size";
} else {
say "fcntl of file failed: $!";
}
if (my $size = fcntl($reader, F_GETPIPE_SZ, 0)) {
say "pipe size: $size";
} else {
say "fcntl of pipe filed: $!";
}
可能的輸出:
fcntl of file failed: Bad file descriptor
pipe size: 65536
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/456522.html
標籤:perl ubuntu file-descriptor fcntl
