一文读懂Linux系统的write调用
本文旨在澄清Linux系统中的write调用特性。许多人对write调用的原子性存在疑问,本文将通过实例和分析给出答案。
首先,明确一点,write调用并不能保证整个写操作是源码拉面原子的。以写入字节的缓冲区到文件为例,Linux内核并不能确保这个操作在单次调用中顺利完成,因为存在一些不可忽视的因素。尽管如此,write设计的初衷是考虑到系统的复杂性和安全性,它保证的是在共享文件描述符的上下文中,每个write调用在写入数据时是原子且不可中断的,即线程或进程之间的写入顺序不会交错。
当两个独立进程分别对文件进行写入,如进程A写'a',进程B写'b',结果可能为'aaabbb'或'bbbaaa',而非交错。梦田票务源码若希望避免交错,需要在打开文件时使用O_APPEND模式。
write调用的原子性保障主要局限于共享文件结构的范围,而非独立文件。在多线程或多进程共享文件时,用户程序需要自行处理短写问题,例如使用锁保护,以确保写入完整。
一些关键应用,taro前端源码教程如Apache和Nginx的日志记录,通过使用APPEND模式来保证独立的原子写入。然而,即便有这些保证,我自己的一个分析TCP数据包程序实例中,尽管理论上应保证原子性,但有时仍会发现数据包信息被覆盖,这提示了潜在的问题。
在深入调查后,车友app源码我发现了write调用在3.社区版内核中存在race条件。通过分析代码,我发现了一个在1和2或者2和3之间可能发生并发问题的场景。通过加载特定模块和调整操作,我成功重现了问题,验证了write调用的原子性在此版本中并未得到充分保证。
幸运的是,这个问题在3.以后的内核版本中已被修复。通过查阅文档和源码,漂亮发卡网源码我发现该问题早在那时就已经被注意到并修复。从这个经历中,我们学习到在遇到问题时,查阅文档比直接分析代码可能更有效率。
最后,虽然2.6.内核在理论上也存在相同问题,但在Centos这样的稳定版内核中,这些问题通常会被修复,从而避免了实际问题的出现。
System.out.writeåSystem.out.println
System.outçç±»å为PrintStreamï¼
System.out.println('a'); å®é ä¸è°ç¨æ¯PrintStreamçprintln(char c)æ¹æ³ï¼èprintln(char c)æ¹æ³çæºä»£ç 为ï¼
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
å¯è§Printlnè°ç¨äºprint(char c)æ¹æ³ï¼print(char c)æ¹æ³çæºä»£ç å¦ä¸ï¼
public void print(char c) {
write(String.valueOf(c));
}
å¯è§è°ç¨çæ¯write(String s)æ¹æ³ï¼write(String s)ç代ç 为ï¼
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
å½å符串ä¸å«æ'\n'æ¶ä¼å·æ°outï¼æ¤å¤çoutæ¯OutStream对象çå®ä¾ãprintln(String s)æåè°ç¨newLine() æ¹æ³ï¼newLine()ç代ç å¦ä¸:
private void newLine() {
try {
synchronized (this) {
ensureOpen();
textOut.newLine();
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
newLine()ä¼å·æ°outã
System.out.write(a); è°ç¨çæ¯PrintStream.write(int b)æ¹æ³
write(int b) çæºä»£ç å¦ä¸ï¼
public void write(int b) {
try {
synchronized (this) {
ensureOpen();
out.write(b);
if ((b == '\n') && autoFlush)
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
çè¿æºä»£ç ååºè¯¥æç½ä¸¤è ä¹é´çå·®å¼äºï¼println(String s)ä¸ä½ä¼å·æ°outï¼èä¸è¿ä¼åæ¶å·æ°textOutåcharOutï¼èwrite(int b)åªæå½b == '\n'æ¶æå·æ°outãè¿ä¹æ¯ä¸ºä»ä¹å äºSystem.out.write('\n'); åå°±è½æ¾ç¤ºåºæ¥äºï¼é®é¢å°±å¨äºout没æå·æ°ã
楼主ç第äºä¸ªé®é¢å¾å¥½è§£éï¼å 为å¨print(String s)ä¸ï¼ä¼å·æ°textOutåcharOutã
textOutåcharOutæ¯ä»ä¹ï¼çä¸ä¸PrintStreamä¸çå®ä¹ï¼
private BufferedWriter textOut;
private OutputStreamWriter charOut;
textOutåcharOutå¨init(OutputStreamWriter osw)æ¹æ³ä¸åå§åï¼init(OutputStreamWriter osw)ç代ç å¦ä¸ï¼
private void init(OutputStreamWriter osw) {
this.charOut = osw;
this.textOut = new BufferedWriter(osw);
}
init()å½æ°å¨æé å½æ°ä¸è¢«è°ç¨
public PrintStream(OutputStream out, boolean autoFlush) {
this(autoFlush, out);
init(new OutputStreamWriter(this));
}
å¯è§ï¼textOutåcharOutæä½çè¾åºæµåoutæ¯ä¸æ ·çï¼å æ¤å¯¹textOutåcharOutå·æ°åæ¶å·æ°äºoutï¼å æ¤print(String s)å³ä¾¿æ²¡æ'\n'ï¼ä¹åæ ·ä¼ç´æ¥è¾åºåºæ¥ã
linux系统调用之write源码解析(基于linux0.)
Linux系统的write函数在底层操作上与read函数有相似之处。本文主要关注一般文件的写操作,我们首先从入口函数开始解析。
进入file_write函数,它的核心逻辑是根据文件inode中的信息,确定要写入的硬盘位置,即块号。如果目标块已存在,就直接返回块号;若不存在,则需要创建新的块。这个过程涉及到bmap函数,它负责根据文件系统状态为新块申请空间并标记为已使用。
创建新块的过程涉及到文件系统的超级块,通过检查当前块的使用情况,申请一个空闲块,并更新超级块以标记其为已使用。接着,超级块信息会被写回到硬盘,同时返回新建的块号。
回到file_write,处理完块的逻辑后,由于是新创建的块,其内容默认为0。这时,bread函数会读取新块的内容,这部分逻辑可以参考read函数的分析。读取后,用户数据会被写入buffer,同时标记为待写回(脏)状态。重要的是,数据实际上并未立即写入硬盘,而是先存储在缓存中。系统会通过后台线程定期将缓存中的内容刷新到硬盘。
Javascript ä¸ documentçWriteä¸WriteInçåºå«
1ãä½¿ç¨ document.write è¾åº HTML æ ç¾ï¼å°¤å ¶æ¯ <script> æ ç¾ï¼çæ¶åï¼éè¦å°éåæ ç¾è¿è¡è½¬ä¹ï¼å¦åæµè§å¨å¨å¹é éåæ ç¾æ¶åçé误ãè¿æ ·åæ¯æ²¡é®é¢çï¼
document.write('<\/script>');
document.write('<\/body>');
document.write('<\/html>');
å¦æä½ ç document.write æ¯å¨ä¸ä¸ª .js æ件ä¸ï¼åä¸éè¦è¿æ ·åã
2ãdocument.write() ådocument.writeln()åºå«
document.write()ådocument.writelné½æ¯JavaScriptå客æ·ç«¯åå ¥çæ¹æ³
writelnæ¯ä»¥è¡æ¹å¼è¾åºçï¼ä¸è¬æ åµä¸ç¨ä¸¤ç§æ¹æ³è¾åºçææå¨é¡µé¢ä¸æ¯æ²¡æåºå«çï¼ä¸¤ç§æ¹æ³ä» å½å¨æ¥çæºä»£ç æ¶æçå¾åºåºå«ï¼é¤éæ¯è¾åºå°preæxmpå ç´ å
æµè¯ä¸ä¸ï¼
<script>
with(window.open()){
document.write("ç¾åº¦")
document.write("ç¾åº¦")
document.writeln("ç¥é")
document.writeln("ç¥é")
document.writeln("ç¥é")
}
</script>
è¿è¡ä¸é¢ç代ç ï¼å¨æ°å¼ççªå£ä¸:æ¥çï¼æºæ件ï¼å°±å¯ä»¥çå°ï¼writelnæ¯ä»¥è¡æ¹å¼è¾åº
å ³äºä¿çæ ¼å¼ï¼æµè¯ä¸ä¸ï¼
<script>
document.write("<pre>ç¾åº¦")
document.write("ç¾åº¦")
document.writeln("ç¥é")
document.writeln("ç¥é")
document.writeln("ç¥é</pre>")
</script>
3ãdocumentæ æ³å¨æå
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<script language="javascript">
var id_var= new Array() ;
function aa()
{
for (i=0;i <3;i++)
{
id_var[i]=document.forms[0].elements[i].value;
// alert(id_var);//ç¨alertå¯ä»¥æ£å¸¸å¼¹åºæ¯ä¸ªå¼
//document.writeln(id_var);//ç¨documentå¨å½æ°éå°±ä¼æ¥éï¼é误: 'document.forms.0.elements' 为空æä¸æ¯å¯¹è±¡ï¼ä¸åå¨å½æ°éå°±å¯ä»¥ ,åå æ¯å¨ç¬¬ä¸æ¬¡æ§è¡document.writeln(id_var)å°ææ¡£éåï¼æ以åé¢çæ¾ä¸å°å¯¹è±¡
}
document.writeln(id_var);
}
</script>
</HEAD>
<BODY>
<form name="form1" method="post" action="">
<input name="ww" type="text" id="ww" value="1">
<input name="gg" type="text" id="gg" value="2">
<input name="jj" type="text" id="jj" value="3">
<a href="#" onClick="aa()">ç¹å»æµè¯ </a>
</form>
</BODY>
</HTML>
4ãç¨document.close()æ¥å ³éè¾åºæµååä¸åä¸æ ·ã
rè¯è¨write.xlsxå¨åªä¸ªå
xlsxå ãRæ¯ç¨äºç»è®¡åæãç»å¾çè¯è¨åæä½ç¯å¢ãæ ¹æ®æ¥è¯¢ç¸å ³èµææ¾ç¤ºrè¯è¨write.xlsxå¨xlsxå ãRæ¯å±äºGNUç³»ç»çä¸ä¸ªèªç±ãå è´¹ãæºä»£ç å¼æ¾ç软件ï¼å®æ¯ä¸ä¸ªç¨äºç»è®¡è®¡ç®åç»è®¡å¶å¾çä¼ç§å·¥å ·ã
2024-12-26 15:17
2024-12-26 15:11
2024-12-26 14:12
2024-12-26 13:59
2024-12-26 13:15