mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-03-06 01:20:12 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
a6dbd01497
102
published/20180803 UNIX curiosities.md
Normal file
102
published/20180803 UNIX curiosities.md
Normal file
@ -0,0 +1,102 @@
|
||||
UNIX 的怪东西
|
||||
======
|
||||
|
||||
最近我在用我编写的各种工具做更多 UNIX 下的事情,我遇到了两个有趣的问题。这些都不是 “bug”,而是我没想到的行为。
|
||||
|
||||
### 线程安全的 printf
|
||||
|
||||
我有一个 C 程序从磁盘读取一些图像,进行一些处理,并将有关这些图像的输出写入 STDOUT。伪代码:
|
||||
|
||||
```
|
||||
for(imagefilename in images)
|
||||
{
|
||||
results = process(imagefilename);
|
||||
printf(results);
|
||||
}
|
||||
```
|
||||
|
||||
对于每个图像都是独立处理的,因此我自然希望将处理任务分配在各个 CPU 之间以加快速度。我通常使用 `fork()`,所以我写了这个:
|
||||
|
||||
```
|
||||
for(child in children)
|
||||
{
|
||||
pipe = create_pipe();
|
||||
worker(pipe);
|
||||
}
|
||||
|
||||
// main parent process
|
||||
for(imagefilename in images)
|
||||
{
|
||||
write(pipe[i_image % N_children], imagefilename)
|
||||
}
|
||||
|
||||
worker()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
imagefilename = read(pipe);
|
||||
results = process(imagefilename);
|
||||
printf(results);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这是正常的做法:我为 IPC 创建管道,并通过这些管道给子进程 worker 发送图像名。每个 worker _能够_通过另一组管道将其结果写回主进程,但这很痛苦,所以每个 worker 都直接写入共享 STDOUT。这工作正常,但正如人们所预料的那样,对 STDOUT 的写入发生冲突,因此各种图像的结果最终会混杂在一起。那很糟糕。我不想自己设置个锁,但幸运的是 GNU libc 为它提供了函数:[flockfile()][1]。我把它们放进去了……但是没有用!为什么?因为 `flockfile()` 最终因为 `fork()` 的写时复制行为而被限制在单个子进程中。即 `fork()`提供的额外安全性(与线程相比),这实际上最终破坏了锁。
|
||||
|
||||
我没有尝试使用其他锁机制(例如 pthread 互斥锁),但我可以想象它们会遇到类似的问题。我想保持简单,所以将输出发送回父输出是不可能的:这给程序员和运行程序的计算机制造了更多的工作。
|
||||
|
||||
解决方案:使用线程而不是 `fork()`。这有制造冗余管道的好的副作用。最终的伪代码:
|
||||
|
||||
```
|
||||
for(children)
|
||||
{
|
||||
pthread_create(worker, child_index);
|
||||
}
|
||||
for(children)
|
||||
{
|
||||
pthread_join(child);
|
||||
}
|
||||
|
||||
worker(child_index)
|
||||
{
|
||||
for(i_image = child_index; i_image < N_images; i_image += N_children)
|
||||
{
|
||||
results = process(images[i_image]);
|
||||
flockfile(stdout);
|
||||
printf(results);
|
||||
funlockfile(stdout);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
这更简单,如预期的那样工作。我猜有时线程更好。
|
||||
|
||||
### 将部分读取的文件传递给子进程
|
||||
|
||||
对于各种 [vnlog][2] 工具,我需要实现这个操作序列:
|
||||
|
||||
1. 进程打开一个关闭 `O_CLOEXEC` 标志的文件
|
||||
2. 进程读取此文件的一部分(在 vnlog 的情况下直到图例的末尾)
|
||||
3. 进程调用 `exec()` 以调用另一个程序来处理已经打开的文件的其余部分
|
||||
|
||||
第二个程序可能需要命令行中的文件名而不是已打开的文件描述符,因为第二个程序可能自己调用 `open()`。如果我传递文件名,这个新程序将重新打开文件,然后从头开始读取文件,而不是从原始程序停止的位置开始读取。在我的程序上不可以这样做,因此将文件名传递给第二个程序是行不通的。
|
||||
|
||||
所以我真的需要以某种方式传递已经打开的文件描述符。我在使用 Linux(其他操作系统可能在这里表现不同),所以我理论上可以通过传递 `/dev/fd/N` 而不是文件名来实现。但事实证明这也不起作用。在 Linux上(再说一次,也许是特定于 Linux)对于普通文件 `/dev/fd/N` 是原始文件的符号链接。所以这最终做的是与传递文件名完全相同的事情。
|
||||
|
||||
但有一个临时方案!如果我们正在读取管道而不是文件,那么没有什么可以符号链接,并且 `/dev/fd/N` 最终将原始管道传递给第二个进程,然后程序正常工作。我可以通过将上面的 `open("filename")` 更改为 `popen("cat filename")` 之类的东西来伪装。呸!这真的是我们所能做到最好的吗?这在 BSD 上看上去会怎么样?
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://notes.secretsauce.net/notes/2018/08/03_unix-curiosities.html
|
||||
|
||||
作者:[Dima Kogan][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://notes.secretsauce.net/
|
||||
[1]:https://www.gnu.org/software/libc/manual/html_node/Streams-and-Threads.html
|
||||
[2]:http://www.github.com/dkogan/vnlog
|
@ -1,157 +0,0 @@
|
||||
icecoobe translating
|
||||
|
||||
How To Check System Hardware Manufacturer, Model And Serial Number In Linux
|
||||
======
|
||||
Getting system hardware information is not a problem for Linux GUI and Windows users but CLI users facing trouble to get this details.
|
||||
|
||||
Even most of us don’t know what is the best command to get this. There are many utilities available in Linux to get system hardware information such as
|
||||
|
||||
System Hardware Manufacturer, Model And Serial Number.
|
||||
|
||||
We are trying to write possible ways to get this details but you can choose the best method for you.
|
||||
|
||||
It is mandatory to know all these information because it will be needed when you raise a case with hardware vendor for any kind of hardware issues.
|
||||
|
||||
This can be achieved in six methods, let me show you how to do that.
|
||||
|
||||
### Method-1 : Using Dmidecode Command
|
||||
|
||||
Dmidecode is a tool which reads a computer’s DMI (stands for Desktop Management Interface) (some say SMBIOS – stands for System Management BIOS) table contents and display system hardware information in a human-readable format.
|
||||
|
||||
This table contains a description of the system’s hardware components, as well as other useful information such as serial number, Manufacturer information, Release Date, and BIOS revision, etc,.,
|
||||
|
||||
The DMI table doesn’t only describe what the system is currently made of, it also can report the possible evolution (such as the fastest supported CPU or the maximal amount of memory supported).
|
||||
|
||||
This will help you to analyze your hardware capability like whether it’s support latest application version or not?
|
||||
```
|
||||
# dmidecode -t system
|
||||
|
||||
# dmidecode 2.12
|
||||
# SMBIOS entry point at 0x7e7bf000
|
||||
SMBIOS 2.7 present.
|
||||
|
||||
Handle 0x0024, DMI type 1, 27 bytes
|
||||
System Information
|
||||
Manufacturer: IBM
|
||||
Product Name: System x2530 M4: -[1214AC1]-
|
||||
Version: 0B
|
||||
Serial Number: MK2RL11
|
||||
UUID: 762A99BF-6916-450F-80A6-B2E9E78FC9A1
|
||||
Wake-up Type: Power Switch
|
||||
SKU Number: Not Specified
|
||||
Family: System X
|
||||
|
||||
Handle 0x004B, DMI type 12, 5 bytes
|
||||
System Configuration Options
|
||||
Option 1: JP20 pin1-2: TPM PP Disable, pin2-3: TPM PP Enable
|
||||
|
||||
Handle 0x004D, DMI type 32, 20 bytes
|
||||
System Boot Information
|
||||
Status: No errors detected
|
||||
|
||||
```
|
||||
|
||||
**Suggested Read :** [Dmidecode – Easy Way To Get Linux System Hardware Information][1]
|
||||
|
||||
### Method-2 : Using inxi Command
|
||||
|
||||
inxi is a nifty tool to check hardware information on Linux and offers wide range of option to get all the hardware information on Linux system that i never found in any other utility which are available in Linux. It was forked from the ancient and mindbendingly perverse yet ingenius infobash, by locsmif.
|
||||
|
||||
inxi is a script that quickly shows system hardware, CPU, drivers, Xorg, Desktop, Kernel, GCC version(s), Processes, RAM usage, and a wide variety of other useful information, also used for forum technical support & debugging tool.
|
||||
```
|
||||
# inxi -M
|
||||
Machine: Device: server System: IBM product: N/A v: 0B serial: MK2RL11
|
||||
Mobo: IBM model: 00Y8494 serial: 37M17D UEFI: IBM v: -[VVE134MUS-1.50]- date: 08/30/2013
|
||||
|
||||
```
|
||||
|
||||
**Suggested Read :** [inxi – A Great Tool to Check Hardware Information on Linux][2]
|
||||
|
||||
### Method-3 : Using lshw Command
|
||||
|
||||
lshw (stands for Hardware Lister) is a small nifty tool that generates detailed reports about various hardware components on the machine such as memory configuration, firmware version, mainboard configuration, CPU version and speed, cache configuration, usb, network card, graphics cards, multimedia, printers, bus speed, etc.
|
||||
|
||||
It’s generating hardware information by reading varies files under /proc directory and DMI table.
|
||||
|
||||
lshw must be run as super user to detect the maximum amount of information or it will only report partial information. Special option is available in lshw called class which will shows specific given hardware information in detailed manner.
|
||||
```
|
||||
# lshw -C system
|
||||
enal-dbo01t
|
||||
description: Blade
|
||||
product: System x2530 M4: -[1214AC1]-
|
||||
vendor: IBM
|
||||
version: 0B
|
||||
serial: MK2RL11
|
||||
width: 64 bits
|
||||
capabilities: smbios-2.7 dmi-2.7 vsyscall32
|
||||
configuration: boot=normal chassis=enclosure family=System X uuid=762A99BF-6916-450F-80A6-B2E9E78FC9A1
|
||||
|
||||
```
|
||||
|
||||
**Suggested Read :** [LSHW (Hardware Lister) – A Nifty Tool To Get A Hardware Information On Linux][3]
|
||||
|
||||
### Method-4 : Using /sys file system
|
||||
|
||||
The kernel expose some DMI information in the /sys virtual filesystem. So we can easily get the machine type by running grep command with following format.
|
||||
```
|
||||
# grep "" /sys/class/dmi/id/[pbs]*
|
||||
|
||||
```
|
||||
|
||||
Alternatively we can print only specific details by using cat command.
|
||||
```
|
||||
# cat /sys/class/dmi/id/board_vendor
|
||||
IBM
|
||||
|
||||
# cat /sys/class/dmi/id/product_name
|
||||
System x2530 M4: -[1214AC1]-
|
||||
|
||||
# cat /sys/class/dmi/id/product_serial
|
||||
MK2RL11
|
||||
|
||||
# cat /sys/class/dmi/id/bios_version
|
||||
-[VVE134MUS-1.50]-
|
||||
|
||||
```
|
||||
|
||||
### Method-5 : Using dmesg Command
|
||||
|
||||
The dmesg command is used to write the kernel messages (boot-time messages) in Linux before syslogd or klogd start. It obtains its data by reading the kernel ring buffer. dmesg can be very useful when troubleshooting or just trying to obtain information about the hardware on a system.
|
||||
```
|
||||
# dmesg | grep -i DMI
|
||||
DMI: System x2530 M4: -[1214AC1]-/00Y8494, BIOS -[VVE134MUS-1.50]- 08/30/2013
|
||||
|
||||
```
|
||||
|
||||
### Method-6 : Using hwinfo Command
|
||||
|
||||
hwinfo stands for hardware information tool is another great utility that used to probe for the hardware present in the system and display detailed information about varies hardware components in human readable format.
|
||||
|
||||
It reports information about CPU, RAM, keyboard, mouse, graphics card, sound, storage, network interface, disk, partition, bios, and bridge, etc,., This tool could display more detailed information among others like lshw, dmidecode, inxi, etc,.
|
||||
|
||||
hwinfo uses libhd library libhd.so to gather hardware information on the system. This tool especially designed for openSUSE system, later other distributions are included the tool into their official repository.
|
||||
```
|
||||
# hwinfo | egrep "system.hardware.vendor|system.hardware.product"
|
||||
system.hardware.vendor = 'IBM'
|
||||
system.hardware.product = 'System x2530 M4: -[1214AC1]-'
|
||||
|
||||
```
|
||||
|
||||
**Suggested Read :** [hwinfo (Hardware Info) – A Nifty Tool To Detect System Hardware Information On Linux][4]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-check-system-hardware-manufacturer-model-and-serial-number-in-linux/
|
||||
|
||||
作者:[VINOTH KUMAR][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.2daygeek.com/author/vinoth/
|
||||
[1]:https://www.2daygeek.com/dmidecode-get-print-display-check-linux-system-hardware-information/
|
||||
[2]:https://www.2daygeek.com/inxi-system-hardware-information-on-linux/
|
||||
[3]:https://www.2daygeek.com/lshw-find-check-system-hardware-information-details-linux/
|
||||
[4]:https://www.2daygeek.com/hwinfo-check-display-detect-system-hardware-information-linux/
|
@ -0,0 +1,142 @@
|
||||
如何查看 Linux 系统硬件制造商、型号和序列号
|
||||
======
|
||||
获取系统硬件信息对于 Linux 图形界面用户和 Windows 用户都不是问题,但是基于命令行的用户想要获取这些细节时会遇到麻烦。
|
||||
甚至我们中的大多数都不知道获取这些信息最好的命令是什么。Linux 中有许多可用的工具集来获取诸如系统硬件制造商、型号和序列号等系统硬件信息。
|
||||
我们尝试写下获取这些细节的可能的方式,而你能从中挑选最好的。
|
||||
|
||||
你必须知道全部的这些信息,因为当你向硬件制造商提交任何硬件问题时,你会需要它们。
|
||||
这可以通过6种方式来实现,让我给你演示下如何去做。
|
||||
|
||||
### 方式-1:使用 `Dmidecode` 命令
|
||||
|
||||
`Dmidecode` 是一个读取电脑 DMI(桌面管理接口)(有人说 SMBIOS 代表系统管理 BIOS)表内容并且以人类可读的格式显示系统硬件信息的工具。
|
||||
这个表包含系统硬件组件的描述,也包含其它有用的信息诸如序列号、制造商信息、发行日期以及 BIOS 修订版本等等。
|
||||
|
||||
DMI 表不仅描述当前系统是由什么构成的,它还能报告可能的升级信息(比如可以支持的最快的 CPU 或者可以支持的最大的内存容量)。
|
||||
|
||||
这将有助于分析你的硬件兼容性,比如是否支持最新版本的程序。
|
||||
```
|
||||
# dmidecode -t system
|
||||
|
||||
# dmidecode 2.12
|
||||
# SMBIOS entry point at 0x7e7bf000
|
||||
SMBIOS 2.7 present.
|
||||
|
||||
Handle 0x0024, DMI type 1, 27 bytes
|
||||
System Information
|
||||
Manufacturer: IBM
|
||||
Product Name: System x2530 M4: -[1214AC1]-
|
||||
Version: 0B
|
||||
Serial Number: MK2RL11
|
||||
UUID: 762A99BF-6916-450F-80A6-B2E9E78FC9A1
|
||||
Wake-up Type: Power Switch
|
||||
SKU Number: Not Specified
|
||||
Family: System X
|
||||
|
||||
Handle 0x004B, DMI type 12, 5 bytes
|
||||
System Configuration Options
|
||||
Option 1: JP20 pin1-2: TPM PP Disable, pin2-3: TPM PP Enable
|
||||
|
||||
Handle 0x004D, DMI type 32, 20 bytes
|
||||
System Boot Information
|
||||
Status: No errors detected
|
||||
```
|
||||
|
||||
**建议阅读:** [Dmidecode – 获取 Linux 系统硬件信息的简单方式][1]
|
||||
|
||||
### 方式-2:使用 `inxi` 命令
|
||||
|
||||
`inxi` 是 Linux 上查看硬件信息的一个灵巧的小工具,并且提供了大范围的选项来获取全部的硬件信息,这是我在现有的其它 Linux 工具集里所没见到过的。它是由 locsmif 从古老的并且至今看来都异常灵活的 `infobash` 里面分支出来的。
|
||||
|
||||
`inxi` 是一个可以快速显示系统硬件、CPU、驱动、Xorg、桌面、内核、GCC 版本、进程、内存使用以及大量其它有用信息的脚本,也可以用来做技术支持和调试工具。
|
||||
```
|
||||
# inxi -M
|
||||
Machine: Device: server System: IBM product: N/A v: 0B serial: MK2RL11
|
||||
Mobo: IBM model: 00Y8494 serial: 37M17D UEFI: IBM v: -[VVE134MUS-1.50]- date: 08/30/2013
|
||||
```
|
||||
|
||||
**建议阅读:** [inxi – 一个很棒的查看 Linux 硬件信息的工具][2]
|
||||
|
||||
### 方式-3:使用 `lshw` 命令
|
||||
|
||||
`lshw`(指代 Hardware Lister - 硬件监听器)是一个小巧灵活的工具,可以生成诸如内存配置、固件版本、主板配置、CPU 版本和速度、缓存配置、USB、网卡、显卡、多媒体、打印机以及总线速度等机器中各种硬件组件的详细报告。
|
||||
|
||||
它通过读取 `/proc` 目录下各种文件的内容和 DMI 表来生成硬件信息。
|
||||
|
||||
`lshw` 必须以超级用户的权限运行来检测最大数量的信息,否则它将只汇报部分信息。`lshw` 里有一个叫做 `class` 的特殊选项,它将以详细模式显示特定的硬件信息。
|
||||
```
|
||||
# lshw -C system
|
||||
enal-dbo01t
|
||||
description: Blade
|
||||
product: System x2530 M4: -[1214AC1]-
|
||||
vendor: IBM
|
||||
version: 0B
|
||||
serial: MK2RL11
|
||||
width: 64 bits
|
||||
capabilities: smbios-2.7 dmi-2.7 vsyscall32
|
||||
configuration: boot=normal chassis=enclosure family=System X uuid=762A99BF-6916-450F-80A6-B2E9E78FC9A1
|
||||
```
|
||||
|
||||
**建议阅读:** [LSHW (Hardware Lister) – 获取 Linux 硬件信息的灵巧的小工具][3]
|
||||
|
||||
### 方式-4:使用 `/sys` 文件系统
|
||||
|
||||
内核暴露了一些 DMI 信息在 `/sys` 虚拟文件系统里。因此,通过如下方式的运行 `grep` 命令我们能够轻易地获取机器类型。
|
||||
```
|
||||
# grep "" /sys/class/dmi/id/[pbs]*
|
||||
```
|
||||
|
||||
同样,使用 `cat` 命令我们能够仅打印出特定的细节。
|
||||
```
|
||||
# cat /sys/class/dmi/id/board_vendor
|
||||
IBM
|
||||
|
||||
# cat /sys/class/dmi/id/product_name
|
||||
System x2530 M4: -[1214AC1]-
|
||||
|
||||
# cat /sys/class/dmi/id/product_serial
|
||||
MK2RL11
|
||||
|
||||
# cat /sys/class/dmi/id/bios_version
|
||||
-[VVE134MUS-1.50]-
|
||||
```
|
||||
|
||||
### 方式-5:使用 `dmesg` 命令
|
||||
|
||||
`dmesg` 命令是在 Linux 上 `syslogd` 或者 `klogd` 启动前用来写内核消息(启动阶段的消息)的。它通过读取内核的环形缓冲区来获取数据。`dmesg` 在问题诊断或者尝试获取系统硬件信息时非常有帮助。
|
||||
```
|
||||
# dmesg | grep -i DMI
|
||||
DMI: System x2530 M4: -[1214AC1]-/00Y8494, BIOS -[VVE134MUS-1.50]- 08/30/2013
|
||||
```
|
||||
|
||||
### 方式-6:使用 `hwinfo` 命令
|
||||
|
||||
`hwinfo` 表示硬件信息工具,它是另一个很棒的检测当前系统硬件并且以人类可读的方式显示各式各样硬件模块细节信息的工具集。
|
||||
|
||||
它报告关于 CPU、内存、键盘、鼠标、显卡、声音、存储、网络接口、磁盘、分区、BIOS 以及桥接器等信息。这个工具可以比其它的像 `lshw`、`dmidecode` 以及 `inxi` 等工具显示更为详细的信息。
|
||||
|
||||
`hwinfo` 使用 `libhd` 库来收集系统上的硬件信息。该工具是为 `OpenSuse` 系统特别设计的,后续其它的发行版也会将它包含在他们的官方仓库。
|
||||
```
|
||||
# hwinfo | egrep "system.hardware.vendor|system.hardware.product"
|
||||
system.hardware.vendor = 'IBM'
|
||||
system.hardware.product = 'System x2530 M4: -[1214AC1]-'
|
||||
```
|
||||
|
||||
**建议阅读:** [hwinfo (Hardware Info) – 一款灵活的检测 Linux 系统硬件信息的工具][4]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.2daygeek.com/how-to-check-system-hardware-manufacturer-model-and-serial-number-in-linux/
|
||||
|
||||
作者:[VINOTH KUMAR][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[icecoobe](https://github.com/icecoobe)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:https://www.2daygeek.com/author/vinoth/
|
||||
[1]:https://www.2daygeek.com/dmidecode-get-print-display-check-linux-system-hardware-information/
|
||||
[2]:https://www.2daygeek.com/inxi-system-hardware-information-on-linux/
|
||||
[3]:https://www.2daygeek.com/lshw-find-check-system-hardware-information-details-linux/
|
||||
[4]:https://www.2daygeek.com/hwinfo-check-display-detect-system-hardware-information-linux/
|
@ -1,102 +0,0 @@
|
||||
UNIX 的好奇
|
||||
======
|
||||
最近我在用我编写的各种工具做更多 UNIX 下的事情,我遇到了两个有趣的问题。这些都不是 “bug”,而是我没想到的行为。
|
||||
|
||||
### 线程安全的 printf
|
||||
|
||||
我有一个 C 程序从磁盘读取一些图像,进行一些处理,并将有关这些图像的输出写入 STDOUT。伪代码:
|
||||
```
|
||||
for(imagefilename in images)
|
||||
{
|
||||
results = process(imagefilename);
|
||||
printf(results);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
处理对于每个图像是独立的,因此我自然希望在各个 CPU 之间分配处理以加快速度。我通常使用 `fork()`,所以我写了这个:
|
||||
```
|
||||
for(child in children)
|
||||
{
|
||||
pipe = create_pipe();
|
||||
worker(pipe);
|
||||
}
|
||||
|
||||
// main parent process
|
||||
for(imagefilename in images)
|
||||
{
|
||||
write(pipe[i_image % N_children], imagefilename)
|
||||
}
|
||||
|
||||
worker()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
imagefilename = read(pipe);
|
||||
results = process(imagefilename);
|
||||
printf(results);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
这是正常的事情:我为 IPC 创建管道,并通过这些管道发送子 worker 的图像名。每个 worker _能够_通过另一组管道将其结果写回主进程,但这很痛苦,所以每个 worker 都直接写入共享 STDOUT。这工作正常,但正如人们所预料的那样,对 STDOUT 的写入发生冲突,因此各种图像的结果最终会分散。这那很糟。我不想设置我自己的锁,但幸运的是 GNU libc 为它提供了函数:[`flockfile()`][1]。我把它们放进去了......但是没有用!为什么?因为 `flockfile()` 的内部最终因为 `fork()` 的写时复制行为而限制在单个子进程中。即 `fork()`提供的额外安全性(与线程相比),这实际上最终破坏了锁。
|
||||
|
||||
我没有尝试使用其他锁机制(例如 pthread 互斥锁),但我可以想象它们会遇到类似的问题。我想保持简单,所以将输出发送回父输出是不可能的:这给程序员和运行程序的计算机制造了更多的工作。
|
||||
|
||||
解决方案:使用线程而不是 fork。这有制造冗余管道的好的副作用。最终的伪代码:
|
||||
```
|
||||
for(children)
|
||||
{
|
||||
pthread_create(worker, child_index);
|
||||
}
|
||||
for(children)
|
||||
{
|
||||
pthread_join(child);
|
||||
}
|
||||
|
||||
worker(child_index)
|
||||
{
|
||||
for(i_image = child_index; i_image < N_images; i_image += N_children)
|
||||
{
|
||||
results = process(images[i_image]);
|
||||
flockfile(stdout);
|
||||
printf(results);
|
||||
funlockfile(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Much simpler, and actually works as desired. I guess sometimes threads are better.
|
||||
这更简单,实际按照需要的那样工作。我猜有时线程更好。
|
||||
|
||||
### 将部分读取的文件传递给子进程
|
||||
|
||||
对于各种 [vnlog][2] 工具,我需要实现这个次序:
|
||||
|
||||
1. 进程打开一个关闭 O_CLOEXEC 标志的文件
|
||||
2. 进程读取此文件的一部分(在 vnlog 的情况下直到图例的末尾)
|
||||
3. 进程调用 exec 以调用另一个程序来处理已经打开的文件的其余部分
|
||||
|
||||
第二个程序可能需要命令行中的文件名而不是已打开的文件描述符,因为第二个程序可能自己调用 open()。如果我传递文件名,这个新程序将重新打开文件,然后从头开始读取文件,而不是从原始程序停止的位置开始读取。这个不会在我的程序上发生很重要,因此将文件名传递给第二个程序是行不通的。
|
||||
|
||||
所以我真的需要以某种方式传递已经打开的文件描述符。我在使用 Linux(其他操作系统可能在这里表现不同),所以我理论上可以通过传递 /dev/fd/N 而不是文件名来实现。但事实证明这也不起作用。在 Linux上(再说一次,也许是特定于 Linux)对于普通文件 /dev/fd/N 是原始文件的符号链接。所以这最终完成了与传递文件名完全相同的事情。
|
||||
|
||||
但有一个临时方案!如果我们正在读取管道而不是文件,那么没有什么可以符号链接,并且 /dev/fd/N 最终将原始管道传递给第二个进程,然后程序正常工作。我可以通过将上面的 open(“filename”)更改为 popen(“cat filename”)之类的东西来伪装。呸!这真的是我们能做的最好的吗?这在 BSD 上看上去会怎么样?
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: http://notes.secretsauce.net/notes/2018/08/03_unix-curiosities.html
|
||||
|
||||
作者:[Dima Kogan][a]
|
||||
选题:[lujun9972](https://github.com/lujun9972)
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]:http://notes.secretsauce.net/
|
||||
[1]:https://www.gnu.org/software/libc/manual/html_node/Streams-and-Threads.html
|
||||
[2]:http://www.github.com/dkogan/vnlog
|
Loading…
Reference in New Issue
Block a user