Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

select system call behavior

21 views
Skip to first unread message

param

unread,
Jan 31, 2006, 11:18:05 AM1/31/06
to
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.

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.

Kasper Dupont

unread,
Jan 31, 2006, 12:51:12 PM1/31/06
to
param wrote:
>
> 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.

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);

David Schwartz

unread,
Jan 31, 2006, 4:52:18 PM1/31/06
to

"param" <sparam...@gmail.com> wrote in message
news:1138724285....@g47g2000cwa.googlegroups.com...

> 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


param

unread,
Feb 1, 2006, 12:16:03 AM2/1/06
to
Kernel Version is: 2.6.5-7.139-smp

Linux lincoln 2.6.5-7.139-smp #1 SMP Fri Jan 14 15:41:33 UTC 2005 i686
i686 i386 GNU/Linux

param

unread,
Feb 1, 2006, 12:57:30 AM2/1/06
to
>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.

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.

Kasper Dupont

unread,
Feb 1, 2006, 1:12:10 AM2/1/06
to

Try 2.6.15.

Kasper Dupont

unread,
Feb 1, 2006, 1:18:25 AM2/1/06
to
param wrote:
>
> >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.
>
> 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 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.

0 new messages