#之前聊過Windows下面Console.WriteLine的運行過程常用Console.WriteLine原理,你知道嗎?本篇看下它在Linu-x64下面最新.NET9運行過程
在.NET中,通常使用StreamReader和StreamWriter這兩個類別來進行流讀寫入操作,它們的命名空間位於System.IO中。這些類別包含在託管庫System.Runtime.dll中。下面是一個簡單的範例操作:
using (StreamWriter writer = File.CreateText("newfile.txt")) { await writer.WriteLineAsync("First line of example"); await writer.WriteLineAsync("and second line"); }
StreamWriter和StreamReader分別衍生自TextWriter和TextReader。 Console.WriteLine列印出的字串,則是在CLR庫裡面直接透過TextWriter寫入到的資料流/裝置。
例如範例:
static void Main(string[] args) { Console.WriteLine("Call Main"); }
Console.WriteLine會呼叫Out.EnsureInitialized函數,Out即為TextWriter型,程式碼如下:
源码地址:https://github.com/dotnet/runtime/blob/main/src/libraries/System.Console/src/System/Console.cs public static TextWriter Out { get { static TextWriter EnsureInitialized() { lock (s_syncObject) { if (s_out == null) { Volatile.Write(ref s_out, CreateOutputWriter(ConsolePal.OpenStandardOutput())); } return s_out; } } } }
EnsureInitialized函數裡面呼叫了Volatile.Write函數,Volatile.Write函數的意思是,把參數二的值寫入到參數一字段裡面去。這裡的解釋就是把CreateOutputWriter(ConsolePal.OpenStandardOutput())回傳的值寫入s_out字段,s_out也是TextWriter型別。
這裡看下CreateOutputWriter(ConsolePal.OpenStandardOutput())回傳的值是啥。 CreateOutputWriter函數如下:
源码地址:https://github.com/dotnet/runtime/blob/main/src/libraries/System.Console/src/System/Console.cs private static TextWriter CreateOutputWriter(Stream outputStream) { return outputStream == Stream.Null ? TextWriter.Null : TextWriter.Synchronized(new StreamWriter( stream: outputStream, encoding: OutputEncoding.RemovePreamble(), bufferSize: WriteBufferSize, leaveOpen: true) { AutoFlush = true }); }
可以看到CreateOutputWriter回傳的依舊是TextWriter,也就是說Volatile.Write把流數據寫入到流數據,然後從設備上列印出來。
這裡寫入的流資料值到底是什麼呢?繼續看ConsolePal.OpenStandardOutput()函數,它回傳的是Stream類型。
源码地址: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Console/src/System/ConsolePal.Unix.cs public static Stream OpenStandardOutput() { return new UnixConsoleStream(Interop.CheckIo(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDOUT_FILENO)), FileAccess.Write); }
這裡是Linux/Unix下面的操作,OpenStandardOutput裡面實例化了一個UnixConsoleStream類,UnixConsoleStream的建構子裡面,第一個參數是Interop.CheckIo(Interop.Sys.Dup(Interop.Sys.FileDescriptors.STDOUT_FILENO) )。 Interop.Sys.Dup是Linux下面進行文件表項操作的函數。 CheckIo則是個檢查函數,此處可以忽略。
舉個例子,一般的來說Linux下面在終端機上印出一個hello World通常透過printf(“hello Word”)
printf -> stdout(标准输出) -> Dup(STDOUT_FILENO) ->终端输出
可見Linux下面是透過Dup函數傳遞參數STDOUT_FILENO進行終端操作的,UnixConsoleStream第二個參數是FileAccess.Write,表示寫入字串。然後把這個Stream封裝後返回,透過Volatile.Write寫入到終端流裡面列印出來。
那麼其實很清晰了,流程大致如下:
Console.WriteLine ->Out.EnsureInitialized -> ConsolePal.OpenStandardOutput() -> I
以上是.NET9 Linux-x64下Console.WriteLine原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!