syswrite#
כתיבת בתים למטפל קובץ באמצעות קריאת המערכת הגולמית write(2), תוך עקיפת ה־I/O המבוצר של Perl.
syswrite מעביר LENGTH בתים מ־SCALAR ישירות לקרנל באמצעות write(2), תוך דילוג על הבאפר של PerlIO ש־print, printf, ו־write עוברים דרכו. הקרנל עשוי לקבל פחות בתים מהמבוקש - syswrite מחזיר את מה שהוא באמת כתב, וקוד כתוב היטב תמיד בודק. אם LENGTH מושמט, כל ה־SCALAR נכתב. OFFSET אופציונלי מתחיל את הכתיבה במיקום שאינו תחילת המחרוזת.
תקציר#
syswrite FILEHANDLE, SCALAR, LENGTH, OFFSET
syswrite FILEHANDLE, SCALAR, LENGTH
syswrite FILEHANDLE, SCALAR
מה מקבלים בחזרה#
מספר הבתים שנכתבו בפועל, או undef בשגיאה (כאשר $! מוגדר). הספירה המוחזרת יכולה להיות קטנה מ־LENGTH. זה תקין ב־pipe־ים, סוקטים, ומטפלים לא־חוסמים; זו אינה שגיאה. קוד שצריך שכל בית יימסר חייב ללולל:
my $off = 0;
my $len = length $buf;
while ($off < $len) {
my $n = syswrite $fh, $buf, $len - $off, $off;
defined $n or die "write failed: $!";
$off += $n;
}
החזרה של 0 חוקית ומשמעה ״לא נכתבו בתים בקריאה זו, נסו שוב״ - לא סוף־זרם. undef הוא איתות השגיאה היחיד.
מצב גלובלי שהוא נוגע בו#
דוגמאות#
כתיבת מחרוזת מילולית ל־STDOUT, ללא הוספת מפרידים:
syswrite STDOUT, "hello\n"; # 6 bytes written
כתיבת רשומה בגודל קבוע ובדיקת כתיבה קצרה:
my $rec = pack "A8 N", $name, $id; # 12 bytes
my $n = syswrite $fh, $rec;
defined $n or die "syswrite: $!";
$n == length $rec or die "short write: $n of ${\length $rec}";
כתיבה מאמצע ה־buffer באמצעות OFFSET. שימושי בתוך לולאת ניקוז שבה $off עוקב אחרי כמה התקבל עד כה:
my $buf = "ABCDEFGHIJ";
syswrite $fh, $buf, 4, 3; # writes "DEFG"
OFFSET שלילי נספר מהסוף:
my $buf = "ABCDEFGHIJ";
syswrite $fh, $buf, 3, -4; # writes "GHI"
כתיבה לסוקט לא־חוסם וטיפול ב־EAGAIN:
use Errno qw(EAGAIN EWOULDBLOCK);
my $n = syswrite $sock, $buf;
if (!defined $n) {
if ($! == EAGAIN || $! == EWOULDBLOCK) {
# kernel buffer full - try again after select()
} else {
die "syswrite: $!";
}
}
מקרי קצה#
אל תערבבו עם I/O מבוצר על אותו מטפל.
syswriteעוקף אתPerlIO, אךprint,printf,write,seek,tell, ו־eofכולם עוברים דרך שכבות הבאפרינג:perlioו־:crlf. שילובם על מטפל אחד מקלקל את סדר הפלט. בחרו מצב אחד לכל מטפל. אם חייבים לערבב, השתמשו בכללי הסימטריה שלread/sysreadופעלו במכוון.כתיבות קצרות הן הנורמה. pipe־ים, סוקטים, טרמינלים, ומטפלים לא־חוסמים מקבלים שגרתית פחות בתים ממה שהוצע. אידיום לולאת הניקוז לעיל הוא התבנית הנכונה לכל מטפל שבו כתיבות קצרות חשובות.
ערך ההחזרה
0משמעו שהקרנל קיבל אפס בתים בקריאה זו. זה לא סוף־זרם ולא שגיאה; נסו שוב.אורך גדול מהנתונים הזמינים: אם
LENGTHחורג מ־length(SCALAR) - OFFSET, רק הבתים הזמינים נכתבים והספירה הזו מוחזרת.SCALAR ריק: אם ל־
SCALARיש אורך אפס,OFFSETחייב להיות0. כל ערך אחר מעלה חריגה.שכבות
:utf8ו־:encoding(...)מעלות חריגה.syswriteפועל על בתים, לא תווים, ומסרב לכל מטפל הנושא שכבת קידוד UTF-8.:encoding(...)מוסיף:utf8באופן מובלע, אז הוא אסור באותה מידה. השתמשו ב־binmodeלהסרת השכבה, או כתבו דרךprintבמקום זאת.תווים מעל U+00FF במטפל במצב־בתים גם מעלים חריגה - אין דרך לסריאליז את נקודת קוד גדולה מ־
0xFFכבית יחיד. קודדו את המחרוזת מפורשות לפני קריאה ל־syswrite:use Encode qw(encode); syswrite $fh, encode("UTF-8", $text);
pipe שבור / סוקט סגור מעלה
SIGPIPE. הפעולה כברירת מחדל מסיימת את התהליך. התקינו$SIG{PIPE} = 'IGNORE'(או מטפל) כדי להפוך זאת לשגיאתsyswriteרגילה כאשר$!מוגדר ל־EPIPE.מטפל קובץ סגור מחזיר
undefכאשר$!מוגדר ל־"Bad file descriptor"; תחתuse warningsנפלטת אזהרתsyswrite() on closed filehandle.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
sysread- המקבילה לקריאה; אותה סמנטיקת עקיפת־buffer ואותה אזהרת קריאה־קצרהsysopen- פתיחת מטפל ברמתopen(2)כך ש־syswriteיכול לתקשר איתו ללא שכבות תרגוםPerlIOבדרךsysseek- מיקום מחדש של המטפל באמצעותlseek(2), משולב עםsyswriteל־I/O עם גישה אקראית על מטפלים גולמייםprint- המקבילה המבוצרת שבדרך כלל רוצים במקום; מתחשב ב־$,,$\, ו־$|binmode- הסרת שכבת:utf8או:encoding(...)ממטפל כך שניתן להשתמש ב־syswriteעליו$!- בחנו אחרי החזרה שלundefכדי להבחין ביןEAGAINלכישלון אמיתי