[color=blue:0046d02c9b]测试一下,没有问题。原来的程序有一点BUG,已经改正。[/color:0046d02c9b]
named streams pipe /unix kernel example source code sample I_SENDFD I_FDINSERT ioctl af_unix
domain sockets socketpair pass file descriptor /dev/spx I_RCVFD openserver 5.0.0 5.0.2 faststart
1.0.0 1.0.1 full duplex bidrectional
Release
SCO OpenServer Enterprise System Release 5.0.0, 5.0.2
SCO OpenServer Desktop System Release 5.0.0, 5.0.2
SCO FastStart Release 1.0.0, 1.0.1
SCO OpenServer Development System Release 5.0.0, 5.0.2
SCO Open Desktop Release 3.0
SCO Open Desktop Development System Release 3.0
SCO UNIX System V/386 Release 3.2 Development System Version 4.2
How are the I_SENDFD and I_RCVFD ioctl()s properly used? -or- Is there an alternative to
Unix Domain Sockets and passing file descriptors via "access rights" in sendmsg(SSC) and
recvmsg(SSC) function calls, in SCO OpenServer 5? Is there a workaround to the current
lack of support for Unix Domain Sockets in SCO Open Desktop Release 3.0?
The following source code consists of three files. These three files illustrate the proper
use of the I_SENDFD ioctl(S). This provides a functionality similar to Unix Domain sockets
and BSD-style stream pipes. In this example, the server process creates an unnamed streams
pipe by performing open(S) on the streams cloning device /dev/spx twice, and calling the
I_FDINSERT ioctl() function to link the two streams together, thus creating the two ends of
the pipe. The mknod(S) system call is then used to attach the name "/tmp/nspipe.serv" to one
of the file descriptors. This end is then connected to by the client process via open() of
this file name. The client sends a well-known request byte over the pipe and is received by
the server. The server then satisfies the request by sending an open file descriptor to the
file "/tmp/sample_file". Finally, the client makes use of the passed descriptor by writing to
the end of the file.
Makefile:
----------------------------------------------------------------------
all: server client
server: server.c
cc $(CFLAGS) -o server server.c
client: client.c
cc $(CFLAGS) -o client client.c
clean:
-rm -f core /tmp/nspipe.serv /tmp/sample_file client server
----------------------------------------------------------------------
client.c
----------------------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stream.h> /* defines queue_t */
#include <stropts.h> /* defines struct strfdinsert */
#include <fcntl.h>
#define NSPIPESERV "/tmp/nspipe.serv"
#define REQ 5
main()
{
int servfd, filefd, nwrite;
char buf[2];
char newbuf[11]="abcdefghij";
struct strrecvfd recvfd;
struct stat filstat;
if ((servfd = open(NSPIPESERV, O_RDWR)) < 0)
{
perror("open of server pipe failed");
exit(1);
}
buf[0] = REQ;
if (write(servfd, buf, 1) != 1)
{
perror("couldn't write request byte");
exit(1);
}
if (ioctl( servfd, I_RECVFD, &recvfd) < 0)
{
printf("I_RECVFD failed\n");
exit(1);
}
filefd = recvfd.fd;
if (filefd < 3)
{
printf("filefd is not valid\n");
exit(1);
}
/* now try appending to the file */
if (fstat( filefd, &filstat  < 0)
perror( "fstat error"
else
printf("file size before write is: %lu\n", filstat.st_size);
if ( lseek(filefd, 0, 2) < 0 
{
printf( "lseek to end of file error"
exit(1);
}
if ( (nwrite = write(filefd, newbuf, 10)) < 0)
perror( "write error to passed text file fd"
else
{
printf("write to text file fd successful\n");
printf("%d bytes written: %s\n", nwrite, newbuf);
}
if (fstat( filefd, &filstat  < 0)
perror( "fstat error"
else
printf("file size after write is: %lu\n", filstat.st_size);
exit(0);
}
----------------------------------------------------------------------
server.c
-------------------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stream.h> /* defines queue_t */
#include <stropts.h> /* defines struct strfdinsert */
#include <fcntl.h>
#define SPX_DEVICE "/dev/spx"
#define NSPIPESERV "/tmp/nspipe.serv"
#define REQ 5
#define SAMPLEFILE "/tmp/sample_file"
int s_pipe(fd)
int fd[2]; /* two file descriptors returned through here */
{
struct strfdinsert ins;
queue_t *pointer;
/*
* First open the stream clone device "/dev/spx" twice,
* obtaining the two file descriptors.
*/
if ( (fd[0] = open(SPX_DEVICE, O_RDWR)) < 0)
return(-1);
if ( (fd[1] = open(SPX_DEVICE, O_RDWR)) < 0)
{
close(fd[0]);
return(-1);
}
/*
* Now link these two streams together with an I_FDINSERT ioctl.
*/
ins.ctlbuf.buf = (char *) & /* no ctl info, just the ptr */
ins.ctlbuf.maxlen = sizeof(queue_t *);
ins.ctlbuf.len = sizeof(queue_t *);
ins.databuf.buf = (char *) 0; /* no data to send */
ins.databuf.len = -1; /* magic: must be -1, not 0, for stream pipe */
ins.databuf.maxlen = 0;
ins.fildes = fd[1]; /* the fd to connect with fd[0] */
ins.flags = 0; /* nonpriority message */
ins.offset = 0; /* offset of pointer in control buffer */
if (ioctl(fd[0], I_FDINSERT, (char *  &ins) < 0)
{
close(fd[0]);
close(fd[1]);
return(-1);
}
return(0); /* all OK */
}
int ns_pipe( name, fd, rdwr 
char *name;
int fd[2];
char *rdwr;
{
int omask;
struct stat statbuff;
if (s_pipe(fd) < 0)
return(-1);
if (*rdwr == 'r')
{
if (fstat(fd[0], &statbuff) < 0)
{
close(fd[0]);
close(fd[1]);
return(-1);
}
}
else if (*rdwr == 'w')
{
if (fstat(fd[1], &statbuff) < 0)
{
close(fd[0]);
close(fd[1]);
return(-1);
}
}
unlink(name);
omask = umask(0);
if (mknod(name, S_IFCHR | 0666, statbuff.st_rdev) < 0)
{
close(fd[0]);
close(fd[1]);
umask(omask);
return(-1);
}
umask(omask);
return(0);
}
int main( 
{
int servfd[2]; /*streams pipe to pass passfd on*/
int passfd; /*file descriptor to pass over filefd*/
char buf[2];
/* set up pass fd server-named streams pipe */
if (ns_pipe( NSPIPESERV, servfd, "r"  < 0)
{
perror("creation of serv pipe failed");
exit(1);
}
/* now wait til a client request comes in */
if (read( servfd[1], buf, 1) != 1)
{
perror("couldn't read request byte from client");
exit(1);
}
if (buf[0] != REQ)
{
fprintf(stderr,"request byte read was incorrect: %d\n", buf[0]);
exit(1);
}
/* client should be waiting for the file descriptor, let's */
/* open the file and pass it over servfd */
if ((passfd = open(SAMPLEFILE, O_CREAT|O_RDWR)) < 0)
{
perror("open of sample text file failed");
exit(1);
}
if ( ioctl( servfd[1], I_SENDFD, passfd  
{
fprintf(stderr,"I_SENDFD failed\n");
exit(1);
}
exit(0);
}
li2002 回复于:2003-11-07 08:06:20 |
不错,不知道这些资料是那里的,想问一下。 |
nuoran 回复于:2003-11-07 11:32:26 |
不能用send_fd和recv_fd函数么?apue15.3中提到过。 |
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/