I tried the same program on other unix platforms (AIX & HP). Here
select returned with positive value while process (writev) able to
write into FIFO (FIFO was not full) and timed out when the FIFO was
full.
I am not sure, is it how select system call behave on linux. please
help me to understand and also if i am doing anything wrong, please
point out me.
Program:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
int main(int argc,char *argv[])
{
void catch_sigpipe(int);
int fd;
char *buf=malloc(1000); /* on AIX, I used to write 15000 bytes
each time, because */
struct iovec data={buf,1000}; /* PIPE_BUF size 32K on AIX. (on
linux 4K) */
fd_set wfds;
struct timeval tv;
int retval;
if(mkfifo("./pfifo",0644)<0)
{
perror("Error");
exit(1);
}
printf("fifo is successfully created\n");
if((fd=open("./pfifo", O_RDWR|O_NONBLOCK )) == -1)
{
perror("open");
exit(1);
}
while(1)
{
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(fd+1, NULL, &wfds, NULL, &tv);
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
else
printf("No data within five seconds: %d\n",retval);
if(writev(fd,&data,1) == -1)
{
perror("Error");
FD_ZERO(&wfds);
FD_SET(fd, &wfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(fd+1, NULL, &wfds, NULL, &tv);
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
else
printf("No data within five seconds: %d\n",retval);
}
else {
printf("writev successful\n");
sleep(1);
}
}
exit(0);
}
LINUX output:
fifo is successfully created
Data is available now.
writev successful
No data within five seconds: 0
writev successful
No data within five seconds: 0
writev successful
No data within five seconds: 0
writev successful
Here PIPE_BUF size is 4K, You can see from the output the select system
call is timed out even when writev successful.
AIX output:
fifo is successfully created
Data is available now.
writev successful
Data is available now.
writev successful
Error: Resource temporarily unavailable
Data is available now.
Data is available now.
Error: Resource temporarily unavailable
Data is available now.
Data is available now.
Here PIPE_BUF size is 32K, select triggers only when FIFO is full.
What kernel version are you using? The pipe implementation was
changed somewhere in the 2.6 kernels, I don't think what you
describe still happens with the newest kernels.
--
Kasper Dupont -- Rigtige mænd skriver deres egne backupprogrammer
#define _(_)"d.%.4s%."_"2s" /* This is my new email address */
char*_="@2kaspner"_()"%03"_("4s%.")"t\n";printf(_+11,_+6,_,6,_+2,_+7,_+6);
> In my program, every time writing into a FIFO, i made a check to see
> writev system call will block or not using "select system call". But
> select system call did not return positive value (positive value means
> no. of descriptors available to write, in my case 1) even when writev
> will able to write into FIFO (that means FIFO (buffer) is not full).
> Here i used 5 seconds as a time out period. So every time select system
> call is timed out.
To prevent the sender from dribbling if the reader is slow, most
operating systems will not unblock a 'select' waiter unless there is enough
room for the largest write to the pipe that the platform guarantees can be
completed atomically. When you call 'select', the OS has no idea that you
are only planning to write one byte and may wait until more space is
available.
DS
Linux lincoln 2.6.5-7.139-smp #1 SMP Fri Jan 14 15:41:33 UTC 2005 i686
i686 i386 GNU/Linux
But, how platforms (OS) like (AIX & HP) unblocks select system call
even when writev (write) system call able to write one byte into FIFO.
I am seeing different kind of behavior on Solaris. I tried that same
programs on solaris, here PIPE_BUF size is 10K. So, every time i am
writing 4000 btyes:
Solaris output is:
fifo is successfully created
Data is available now.
writev successful
Data is available now.
writev successful
No data within five seconds: 0
Error: Resource temporarily unavailable
>From the output, You can see first two times select is unblocked, in
the 3rd time only is timed out, because only available buffer size is
2240 bytes (3rd time writev tried to write same 4000 bytes).
> When you call 'select', the OS has no idea that you
> are only planning to write one byte and may wait until more space is
> available.
Is it write idea to allow select system call to check more available
space (say PIPE_BUF size)?
think this way, client tries to write 500 bytes, but that time
available pipe size is 400 bytes, so in this situation writev system
call will fail. so i am using select to check writev failed due to FIFO
is full or partially full. If it is partially full (select unblock),so
i can reduce the message size (say reduced to 300 bytes) then i can try
to write. this can be achievable on aix, hp . But using current linux
implementation of select system call is not possible.
If you think my point of view is wrong, please help me to correct.
Try 2.6.15.
I don't think they do.
select shouldn't unblock unless it is possible to write PIPE_BUF
bytes without blocking. On older Linux versions PIPE_BUF was
equivalent to the maximum amount of data you could have in the
pipe. That means if there is just one byte on the pipe, then
there is not enough room for another PIPE_BUF bytes.
On most recent Linux versions this should have changed. I think
now you can have 16 writes of up to 4KB each in the pipe.