发展方向越来越明晰了呢:
掌握一个特定的开发领域,熟练且精通。什么叫熟练,就是在这个领域下,能扶起来一个应用,达成你想要的功能
但向深度,往哪里深呢,我还是更喜欢OS,弄清OS,几乎没问题能挡住你,为什么不向一个框架深入呢?以我目前的认知,要熟悉一个框架就是看说明书
另一方向,需要学习大量的开源代码来掌握编程模式,编程套路
更深一些,即算法,它可以有理论依据的、巧妙地去解决一个复杂问题,而不是去凑(数学之美这本书告诉我的),比如一个有限状态机的实现过程,比如看看Spring是如何使用IoC来实现对象组合的(需要的是思想,设计思想,不是实现细节),比如说,Apache HTTPClient是如何探测TCP连接是否新鲜的(我想这个即使在C语言中也是通用的)。
问题描述
好了,切入正题。
我们的测试又卡住了。对surefire JVM,jstack
看出main线程在RUNNABLE
, 并且方法栈顶是在writeBytes()
,一个native method处,转化线程ID到Linux TaskId,再来一剂strace
,果然看到write(1, "8,3 UTF-8....., 216)
停在这里不返回了,显然是写阻塞了。
此时,我cat /proc/taskId/1
,把文件内容读出来,这个JVM进程也就结束了,还输出个BYE.
问题分析
可是1不是stdout吗?这玩意还能阻塞?
它真的是stdout吗?你看这个进程到控制台输出了吗?没有,查看task的fd,1果然是个pipe
文件,dup
忘了…
pipe写是同步的吗?这真没想过,一个管道,有大小没有?
pipe man手册
If a process attempts to read from an empty pipe, then read(2)
will block until data is available. If a process attempts to
write to a full pipe (see below), then write(2) blocks until
sufficient data has been read from the pipe to allow the write to
complete. Nonblocking I/O is possible by using the fcntl(2)
F_SETFL operation to enable the O_NONBLOCK open file status flag.
The communication channel provided by a pipe is a byte stream:
there is no concept of message boundaries.
如果一个进程尝试从一个空pipe去读,则read
系统调用就会阻塞直到有数据。如果一个进程尝试向一个满pipe
写入数据,则write系统调用会阻塞直到有足够的数据被读走允许写。非阻塞IO是允许通过系统调用fctnl
系统调用的F_SETFL
操作使能O_NONBLOCK
打开文件状态标记。
pipe提供的通信channel是一个stream,没有消息边界的概念。
在Linux2.6.35之后,pipe默认大小为16个页大小,64KB,但是又有个最大pipe大小, /proc/sys/fs/pipe-max-size
为1MB, 那么这个满,是以谁为准呢?StackOverFlow 中指出:可以通过fcntl
指定F_SETPIPE_SZ
,否则为默认64KB.
In Linux versions before 2.6.11, the capacity of a pipe was the
same as the system page size (e.g., 4096 bytes on i386).
Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes
in a system with a page size of 4096 bytes). Since Linux 2.6.35,
the default pipe capacity is 16 pages, but the capacity can be
queried and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ
operations. See fcntl(2) for more information.
The following ioctl(2) operation, which can be applied to a file
descriptor that refers to either end of a pipe, places a count of
the number of unread bytes in the pipe in the int buffer pointed
to by the final argument of the call:
ioctl(fd, FIONREAD, &nbytes);
The FIONREAD operation is not specified in any standard, but is
provided on many implementations.
结果显示当然是同步的,否则也不会阻塞,那么读的那一端为啥子不读了?