Mail Archives: cygwin/2012/10/04/15:46:46
X-Recipient: | archive-cygwin AT delorie DOT com
|
X-SWARE-Spam-Status: | No, hits=-1.5 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,RCVD_IN_HOSTKARMA_YE
|
X-Spam-Check-By: | sourceware.org
|
X-Eon-Dm: | sj1-dm103
|
X-Eon-Sig: | AQMoEGNQbeeKyp77OgIAAAAB,e5902c4b9f881ab8776797287eb2cadc
|
From: | bob <bob AT icanprogram DOT com>
|
To: | cygwin AT cygwin DOT com
|
Subject: | Fifo blocking and performance issues - some more code snips
|
Date: | Thu, 04 Oct 2012 15:46:17 -0400
|
Message-ID: | <2229037.KBDcDZC6oz@bob-kubuntu>
|
User-Agent: | KMail/4.8.5 (Linux/3.2.0-31-generic; KDE/4.8.5; x86_64; ; )
|
MIME-Version: | 1.0
|
X-Proofpoint-Virus-Version: | vendor=fsecure engine=2.50.10432:5.7.7855,1.0.431,0.0.0000 definitions=2012-10-04_05:2012-10-04,2012-10-04,1970-01-01 signatures=0
|
X-Proofpoint-Spam-Details: | rule=notspam policy=default score=0 spamscore=0 ipscore=0 suspectscore=1 phishscore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=6.0.2-1203120001 definitions=main-1210040221
|
Mailing-List: | contact cygwin-help AT cygwin DOT com; run by ezmlm
|
List-Id: | <cygwin.cygwin.com>
|
List-Subscribe: | <mailto:cygwin-subscribe AT cygwin DOT com>
|
List-Archive: | <http://sourceware.org/ml/cygwin/>
|
List-Post: | <mailto:cygwin AT cygwin DOT com>
|
List-Help: | <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
|
Sender: | cygwin-owner AT cygwin DOT com
|
Mail-Followup-To: | cygwin AT cygwin DOT com
|
Delivered-To: | mailing list cygwin AT cygwin DOT com
|
Forgot to mention in my last code snip post that the Linux code below is the
"desired" behavior of the fifos to match the existing Linux code in the SIMPL
toolkit.
In this Linux code snip we open the receive end of the fifo as RDWR (without
the O_NONBLOCK flag) and Linux conveniently allows that open to occur even if
the other end of the fifo isn't yet there. In Cygwin this open blocks, hence
the need for the O_NONBLOCK flag. Furthermore the Linux code conveniently
blocks on the read() call. In Cygwin this read doesn't block (probably
because it has been open O_NONBLOCK to overcome the open blocking issue)
hence the need for the select() hack.
I haven't had time to replicate the blocking WRONLY fifo open problem that I
noticed in my SIMPL toolkit testing on Cygwin. Early indications is that
this open blocks if at least one other process has opened the fifo WRONLY and
remains alive. Once again the behavior on Linux is that this open doesn't
block regardless of how many other processes have the fifo open WRONLY.
Thanks again for all your help.
bob
PS.
The astute reader might be asking why RDWR and not RDONLY. Turns out that
RDWR fifos on Linux allow for some detection of vanished partners which helps
with cleanup in such scenerios. The behavior on Cygwin is the same with
RDONLY and RDWR fifos in that the open blocks until the other partner opens the
fifo.
PS2.
The other astute reader will recognize the QNX style Send-Receive-Reply
message pass in these code snips. The receiver opens a fifo RDWR and blocks
on a read() waiting for an integer value. The sender opens the receiver's
fifo WRONLY and submits an integer and then blocks on its own RDWR fifo waiting
for a response. Meanwhile the receiver read() unblocks and reads out an
integer. The receiver then submits the response integer to a WRONLY end of
the sender's reply fifo. ie. a synchronous message pass. In the SIMPL
toolkit this integer exchange on the fifos is used to synchronize a shared
memory exchange of the actual message bytes.
========= begin sender2.c ===============
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/timeb.h>
int blocked_read(int, char *, int);
int main(int argc, char *argv[])
{
char command[80];
char fifoname[80];
int fd=-1;
int rfd;
int i;
int j;
int *r;
int bytesToGo;
int numBytes;
char buf[5];
char *p;
int rc;
struct timeb before;
struct timeb after;
int msec;
printf("fifo sender starting\n");
sprintf(fifoname,"/tmp/fsender");
mkfifo(fifoname, 0666);
chmod(fifoname, 0666);
printf("starting receiver2\n");
sprintf(command,"./receiver2&");
rc=system(command);
printf("receiver2 started\n");
sleep(2);
fd=open(fifoname, O_RDWR);
//fd=open(fifoname, O_RDWR|O_NONBLOCK);
rfd=open("/tmp/freceiver", O_WRONLY);
ftime(&before);
for(j=1; j<100; j++)
{
printf("j=%d\n",j);
write(rfd,&j,sizeof(int));
numBytes=0;
memset(buf,0,4);
p=buf;
for(i=0; i< 10; i++)
{
bytesToGo=sizeof(int) - numBytes;
printf("bytesToGo=%d numBytes=%d\n",bytesToGo,numBytes);
if(bytesToGo <= 0) break;
rc=blocked_read(fd,p,bytesToGo);
printf("sender rc[%d]=%d\n",i,rc);
if(rc == 0)
{
printf("got eof\n");
}
else
if(rc == -1)
{
printf("%s\n",strerror(errno));
}
else
{
numBytes+=rc;
p+=rc;
}
} //end for i
printf("buf: 0x%X-%X-%X-%X\n",buf[0],buf[1],buf[2],buf[3]);
r=(int *)buf;
printf("reply[%d]=%d\n",j,*r);
} // end for j
ftime(&after);
msec=(after.time - before.time)*1000 + (after.millitm - before.millitm);
printf("%d messages took %d ms\n",j, msec);
sleep(1);
unlink(fifoname);
unlink("/tmp/freceiver");
exit(0);
} // end sender
int blocked_read(int fd, char *buff, int size)
{
int rc;
//fd_set inset;
//FD_ZERO(&inset);
//FD_SET(fd, &inset);
//printf("send: before select\n");
//select(fd+1, &inset, NULL, NULL, NULL);
printf("send: before read\n");
rc=read(fd,buff,size);
printf("send: read rc=%d\n",rc);
return(rc);
} // end blocked_read
========= end sender2.c ================
========== begin receiver2.c ===========
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/select.h>
int blocked_read(int, char *, int);
int main(int argc, char *argv[])
{
char command[80];
char fifoname[80];
int fd;
int rfd;
int dummy;
int i;
int j;
int k;
int *r;
int bytesToGo;
int numBytes;
char buf[4];
char *p;
int rc;
printf("fifo receiver starting\n");
sprintf(fifoname,"/tmp/freceiver");
mkfifo(fifoname, 0666);
chmod(fifoname, 0666);
fd=open(fifoname, O_RDWR);
//fd=open(fifoname, O_RDWR | O_NONBLOCK);
for(k=0; k<99; k++)
{
numBytes=0;
p=buf;
for(i=0; i< 10; i++)
{
bytesToGo=sizeof(int) - numBytes;
if(bytesToGo <= 0) break;
// rc=read(fd,p,bytesToGo);
rc=blocked_read(fd,p,bytesToGo);
printf("recv rc[%d]=%d\n",i,rc);
if(rc == 0)
{
printf("recv eof\n");
}
else
if(rc == -1)
{
printf("%s\n",strerror(errno));
}
else
{
numBytes+=rc;
p+=rc;
}
} // end for i
r=(int *)buf;
j=*r;
printf("received[%d]=%d\n",k,j);
j++;
// sleep(1);
rfd=open("/tmp/fsender", O_WRONLY);
write(rfd,&j,sizeof(int));
close(rfd);
} // end for k
unlink(fifoname);
exit(0);
} // end receiver
int blocked_read(int fd, char *buff, int size)
{
int rc;
//fd_set inset;
//FD_ZERO(&inset);
//FD_SET(fd, &inset);
//printf("recv: before select\n");
//select(fd+1, &inset, NULL, NULL, NULL);
printf("recv: before read\n");
rc=read(fd,buff,size);
printf("recv: read rc=%d\n",rc);
return(rc);
} // end blocked_read
========== end receiver2.c =============
========= begin linux.out2 =============
sender2
fifo sender starting
starting receiver2
receiver2 started
fifo receiver starting
recv: before read
j=1
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[0]=1
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x2-0-0-0
reply[1]=2
j=2
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[1]=2
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x3-0-0-0
reply[2]=3
j=3
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[2]=3
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x4-0-0-0
reply[3]=4
j=4
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[3]=4
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5-0-0-0
reply[4]=5
j=5
bytesToGo=4 numBytes=0
send: before read
recv: read rc=4
recv rc[0]=4
received[4]=5
recv: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x6-0-0-0
reply[5]=6
...
j=92
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[91]=92
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5D-0-0-0
reply[92]=93
j=93
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[92]=93
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5E-0-0-0
reply[93]=94
j=94
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[93]=94
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x5F-0-0-0
reply[94]=95
j=95
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[94]=95
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x60-0-0-0
reply[95]=96
j=96
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[95]=96
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x61-0-0-0
reply[96]=97
j=97
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[96]=97
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x62-0-0-0
reply[97]=98
j=98
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[97]=98
recv: before read
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x63-0-0-0
reply[98]=99
j=99
bytesToGo=4 numBytes=0
recv: read rc=4
recv rc[0]=4
received[98]=99
send: before read
send: read rc=4
sender rc[0]=4
bytesToGo=0 numBytes=4
buf: 0x64-0-0-0
reply[99]=100
100 messages took 8 ms
========= end linux.out2 ===============
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
- Raw text -