Случайно наткнулся на загадочное (для меня) поведение программы.
Вот протокол
avp@avp-ubu1:~/src/ig/tst$ cat tpoll.c
#include
main ()
{
int lw = write(fileno(stdin),"xaxa
",5);
char buf[100];
int lr = read(fileno(stdout),buf,99);
buf[(lr > 0)? lr:0] = 0;
printf ("lw = %d lr = %d buf = [%s]
",lw,lr,buf);
exit(0);
}
avp@avp-ubu1:~/src/ig/tst$ gcc tpoll.c
avp@avp-ubu1:~/src/ig/tst$ ./a.out
xaxa
js39993
lw = 5 lr = 8 buf = [js39993
]
avp@avp-ubu1:~/src/ig/tst$ g++ tpoll.c
avp@avp-ubu1:~/src/ig/tst$ ./a.out
xaxa
jsk393
lw = 5 lr = 7 buf = [jsk393
]
avp@avp-ubu1:~/src/ig/tst$
avp@avp-ubu1:~/src/ig/tst$ cat /etc/issue
Ubuntu 10.04.4 LTS
\l
avp@avp-ubu1:~/src/ig/tst$ env | grep TERM
TERM=xterm
COLORTERM=gnome-terminal
avp@avp-ubu1:~/src/ig/tst$ ps -ef | grep term
avp 1536 1 0 Oct24 ? 00:00:03 gnome-terminal
avp 2223 1538 0 01:17 pts/0 00:00:00 grep --color=auto term
avp@avp-ubu1:~/src/ig/tst$
avp@avp-ubu1:~/src/ig/tst$
Скажу откровенно, сам пока еще ответ нигде не искал. Возможно это общеизвестный факт, а может нет.
Если кто знает, почему такое происходит, объясните, пожалуйста.
В винде все, как и ожидается
c:/Users/avp/src/cc/hashcode $ gcc tpoll.c
c:/Users/avp/src/cc/hashcode $ ./a
lw = -1 lr = -1 buf = []
c:/Users/avp/src/cc/hashcode $
Реально убунта стоит под виндой в VirtualBox.
UPD
Дополнил программу и немного позапускал. Видимо обычно sh запускается с дапами одного девайса и это наследуется. В виде исключения нашел mpi на кластере.
#include
static void
pristat (char *what, struct stat *sbuf)
{
printf ("%s stat:
S_ISREG %s, S_ISCHR %s, S_ISFIFO %s, S_ISSOCK %s
\
st_dev=%ld st_ino=%ld st_rdev=%ld st_mode=%lx
", what,
S_ISREG(sbuf->st_mode)? "Yes":"No",
S_ISCHR(sbuf->st_mode)? "Yes":"No",
S_ISFIFO(sbuf->st_mode)? "Yes":"No",
S_ISSOCK(sbuf->st_mode)? "Yes":"No",
(long)sbuf->st_dev, (long)sbuf->st_ino, (long)sbuf->st_rdev, (long)sbuf->st_mode);
}
static char*
stdiff (struct stat *sbuf1, struct stat *sbuf2, char *buf)
{
*buf = 0;
if (sbuf1->st_dev != sbuf2->st_dev)
strcat(buf,"st_dev ");
if (sbuf1->st_ino != sbuf2->st_ino)
strcat(buf,"st_ino ");
if (sbuf1->st_mode != sbuf2->st_mode)
strcat(buf,"st_mode ");
if (sbuf1->st_nlink != sbuf2->st_nlink)
strcat(buf,"st_nlink ");
if (sbuf1->st_uid != sbuf2->st_uid)
strcat(buf,"st_uid ");
if (sbuf1->st_gid != sbuf2->st_gid)
strcat(buf,"st_gid ");
if (sbuf1->st_rdev != sbuf2->st_rdev)
strcat(buf,"st_rdev ");
if (sbuf1->st_size != sbuf2->st_size)
strcat(buf,"st_size ");
if (sbuf1->st_blksize != sbuf2->st_blksize)
strcat(buf,"st_blksize ");
if (sbuf1->st_blocks != sbuf2->st_blocks)
strcat(buf,"st_blocks ");
if (sbuf1->st_atime != sbuf2->st_atime)
strcat(buf,"st_atime ");
if (sbuf1->st_mtime != sbuf2->st_mtime)
strcat(buf,"st_mtime ");
if (sbuf1->st_ctime != sbuf2->st_ctime)
strcat(buf,"st_ctime ");
return buf;
}
main ()
{
int lw = write(fileno(stdin),"xaxa
",5);
char buf[1000];
int lr = read(fileno(stdout),buf,99);
buf[(lr > 0)? lr:0] = 0;
printf ("lw = %d lr = %d buf = [%s]
",lw,lr,buf);
fprintf(stderr,"Try read stderr:");
lr = read(fileno(stderr),buf,99);
buf[(lr > 0)? lr:0] = 0;
printf ("stderr: lr = %d buf = [%s]
",lr,buf);
struct stat sbufi, sbufo, sbufe;
fstat(fileno(stdin),&sbufi);
fstat(fileno(stdout),&sbufo);
fstat(fileno(stderr),&sbufe);
int diffio = memcmp(&sbufi,&sbufo,sizeof(sbufi)),
diffoe = memcmp(&sbufi,&sbufo,sizeof(sbufi));
if (diffio == 0 && diffoe == 0)
pristat("All",&sbufi);
else {
printf ("stdin & stdout differ in %s
stdout & stderr differ in %s
",
stdiff(&sbufi,&sbufo,buf), stdiff(&sbufo,&sbufe,&buf[500]));
pristat("stdin",&sbufi);
pristat("stdout",&sbufo);
pristat("stderr",&sbufe);
}
exit(0);
}
Это обычная Xubuntu (в Emacs eshell то же самое)
avp@avp-xub11:~/src/tst$ gcc tstdio.c
avp@avp-xub11:~/src/tst$ ./a.out
xaxa
read STDOUT
lw = 5 lr = 12 buf = [read STDOUT
]
Try read stderr:read STDERR
stderr: lr = 12 buf = [read STDERR
]
All stat:
S_ISREG No, S_ISCHR Yes, S_ISFIFO No, S_ISSOCK No
st_dev=11 st_ino=6 st_rdev=34819 st_mode=2190
avp@avp-xub11:~/src/tst$
avp@avp-xub11:~/src/tst$
Это RedHat на кластере, сначала вычислительный узел по mpi, потом "рабочая среда".
[root@manager soft]# mpirun -hosts cn01 ./a.out
lw = -1 lr = -1 buf = []
stderr: lr = -1 buf = []
stdin & stdout differ in st_ino
stdout & stderr differ in st_ino
stdin stat:
S_ISREG No, S_ISCHR No, S_ISFIFO Yes, S_ISSOCK No
st_dev=8 st_ino=333128 st_rdev=0 st_mode=1180
stdout stat:
S_ISREG No, S_ISCHR No, S_ISFIFO Yes, S_ISSOCK No
st_dev=8 st_ino=333129 st_rdev=0 st_mode=1180
stderr stat:
S_ISREG No, S_ISCHR No, S_ISFIFO Yes, S_ISSOCK No
st_dev=8 st_ino=333130 st_rdev=0 st_mode=1180
Try read stderr:[root@manager soft]#
[root@manager soft]#
[root@manager soft]# ./a.out
xaxa
jkks
lw = 5 lr = 5 buf = [jkks
]
Try read stderr:Cluster manager
stderr: lr = 16 buf = [Cluster manager
]
All stat:
S_ISREG No, S_ISCHR Yes, S_ISFIFO No, S_ISSOCK No
st_dev=11 st_ino=3 st_rdev=34816 st_mode=2190
[root@manager soft]#
Можно подвести итог. Когда увидишь такое в первый раз, то крайне неожиданно (а я наткнулся в результате своей невнимательности в тестовой программе), а потом понимаешь, что а почему бы и нет?
Ответ
Хе, забавно. Наверное, все эти стандартные файловые дескрипторы присоединены к /dev/tty, который во всех случаях открывался с O_RDWR.
Комментариев нет:
Отправить комментарий