.NET9 Linux-x64下Console.WriteLine原理

系统 Linux
StreamWriter和StreamReader分别派生自TextWriter和TextReader。Console.WriteLine打印出的字符串,则是在CLR库里面直接通过TextWriter写入到的数据流/设备。

1.前言

之前聊过Windows下面Console.WriteLine的运行过程常用Console.WriteLine原理,你知道吗?本篇看下它在Linu-x64下面最新.NET9运行过程

2.托管代码

.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");
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

StreamWriter和StreamReader分别派生自TextWriter和TextReader。Console.WriteLine打印出的字符串,则是在CLR库里面直接通过TextWriter写入到的数据流/设备。

比如例子:

static void Main(string[] args)
{
   Console.WriteLine("Call Main");
}
  • 1.
  • 2.
  • 3.
  • 4.

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;
                    }
                }
            }
        }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

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
            });
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

可以看到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);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

这里是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) ->终端输出
  • 1.

可见Linux下面是通过Dup函数传递参数STDOUT_FILENO进行终端操作的,UnixConsoleStream第二个参数是FileAccess.Write,表示写入字符串。然后把这个Stream封装后返回,通过Volatile.Write写入到终端流里面打印出来。

那么其实很清晰了,流程大致如下:

Console.WriteLine ->Out.EnsureInitialized -> ConsolePal.OpenStandardOutput() -> I
  • 1.
责任编辑:武晓燕 来源: 江湖评谈
相关推荐

2024-02-19 00:00:00

Console函数链接库

2024-03-11 10:21:53

.NET9调用FCall

2024-11-27 13:17:21

2024-12-09 00:00:06

2009-06-25 09:03:42

Linux

2024-11-20 16:02:47

.NET 9LINQ开发

2009-12-17 10:05:07

LinuxdtAgeiaPhys

2023-09-21 08:46:44

操作系统windows 10内存

2025-03-05 10:00:00

.NET 9C#开发

2025-01-03 08:29:53

2025-03-03 00:48:12

微软.NET 9Java

2025-03-03 02:25:00

.NET 9JSON序列化

2009-03-04 09:10:53

Windows 7Beta7048x64和703

2009-08-27 10:31:36

ChromiumLinux64位程序

2025-02-06 13:57:26

2012-03-02 09:32:33

Linux桌面系统

2021-10-15 10:24:04

Windows 11操作系统微软

2023-09-25 10:29:21

CPUAArch64x86_64

2024-02-20 08:40:08

.NET 9智能应用开发

2021-06-07 15:20:22

Linux X861MB内存BIOS
点赞
收藏

51CTO技术栈公众号