- 论坛徽章:
- 0
|
本来最近想写一个进程间传递文件描述符的程序,从网上copy了一段代码,先是在AIX上面编译运行,程序成功运行,但是移植到HP UNIX上,运行后,发现sendmsg函数返回错误,errno的错误码是“Bad file number”错误。本人在网上查过一些资料,此程序在SCO上也会出现“Bad file number”错误,但是都说AIX和HP UNIX可以成功执行。前两天,本来将编译后的程序copy到另外一台HP UNIX机器,发现sendmsg函数居然成功了,但至今在测试的HP UNIX机器上都不能成功。请教一下各位大牛,是否也有遇到我这种情况的,是不是和HP UNIX机器设置相关,是否需要打开流管道神马之类的。在线等答案,急!!!
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <time.h>
#include <stdarg.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <assert.h>
#include <signal.h>
#include <sys/param.h>
#define IDLE 0
#define BUSY 1
#define END 2
#define MAXLINE 1024
#define SA struct sockaddr
typedef struct pro {
pid_t id; /*进程的进程ID*/
int fd; /*与父进程通信的描述符*/
int flags; /*进程当前状态*/
int cnt; /*进程服务的次数*/
}process;
process *mypid; /*进程池*/
ssize_t write_the_fd(int fd, void *ptr, size_t nbytes, int sendfd);
pid_t make_child( int i, int listenfd );
ssize_t read_the_fd(int fd, void *ptr, size_t nbytes, int *recvfd);
void child_func(pid_t pid, int id, int fd);
void clr(int signo);
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf, MAXLINE, fmt, ap);
if (errnoflag)
snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s", strerror(error));
strcat(buf, "\n";
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(NULL); /* flushes all stdio output streams */
}
void err_sys(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
exit(1);
}
void err_quit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(0, 0, fmt, ap);
va_end(ap);
exit(1);
}
int max(int a, int b)
{
return a > b ? a : b;
}
int main( int argc, char **argv ) {
int nchild, fdmax, listenfd, connfd, i, len, nselect, port;
char c;
struct sockaddr_in addr, clientaddr;
signal(SIGCHLD, clr);
signal(SIGINT, clr);
fd_set rset, oset;
if(argc != 3)
err_quit("args";
listenfd = socket( AF_INET, SOCK_STREAM, 0 );/*服务器监听套接字*/
if( listenfd < 0 ) {
err_sys("socket";
}
nchild = atoi(argv[1]);
port = atoi(argv[2]);
mypid = (struct pro *)malloc( nchild * sizeof( struct pro) );
bzero( &addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(listenfd, (SA *)&addr, sizeof(struct sockaddr));
fdmax = listenfd; /*用于select */
for( i = 0; i < nchild; i++ ) {
make_child(i, listenfd); /*创建子进程并等待给客户服务*/
} /*传入listenfd子进程关闭监听套接字*/
int idle = nchild; /*当前空闲的子进程*/
len = sizeof(struct sockaddr);
FD_ZERO(&oset);
FD_ZERO(&rset);
listen(listenfd,5);
FD_SET(listenfd, &oset);
for( ; {
if(idle == 0)
FD_CLR(listenfd, &oset); /*若没有空闲子进程,则禁止accept新连接*/
else
FD_SET(listenfd, &oset);
rset = oset;
nselect = select(fdmax+1, &rset, NULL, NULL, NULL);
printf("loop select = %d\n", nselect);
if( FD_ISSET(listenfd, &rset) ) { /*收到客户端连接请求*/
connfd = accept(listenfd, (SA *)&clientaddr, (socklen_t *)&len);
for( i = 0; i < nchild; i++) {
if(mypid[i].flags == IDLE) { /*查找可供服务的子进程*/
break;
}
}
/* */
//assert(i < nchild);
if (i >= nchild)
{
printf("poll enough\n";
continue;
}
printf("the id is %d [connfd = %d]\n", i, connfd);
mypid[i].flags = BUSY; /*改变子进程状态*/
mypid[i].cnt ++; /*子进程服务次数*/
FD_SET(mypid[i].fd, &oset); /*加入描述集,等待子进程*/
fdmax = max(fdmax ,mypid[i].fd);
idle --; /*空闲进程减少*/
/*通知子进程*/
write_the_fd(mypid[i].fd, " ", 1,connfd);/*把连接套接字传送给子进程*/
printf("write the fd\n";
close(connfd); /*因为有一个connfd在飞,所以这个可以关闭*/
if(--nselect ==0)
continue;
}
else {
for(i = 0; i < nchild; i++ )
{
printf("child cancle\n";
if(FD_ISSET(mypid[i].fd , &rset))
{
read(mypid[i].fd, &c, 1);
mypid[i].flags = IDLE;
FD_CLR(mypid[i].fd, &oset);
idle ++;
nselect--;
printf("idle = %d\n", idle);
}
if(nselect == 0)
break;
}
}
}
}
void clr(int signo)
{
pid_t pid;
while( (pid = waitpid(-1, NULL, WNOHANG)) > 0 )
{
printf("The child %d is done\n", pid);
}
sleep(2);
printf("process %d cancel!!!\n", getpid());
fflush(stdout);
kill(getpid(), SIGTERM);
return;
}
pid_t make_child( int i, int listenfd ) {
pid_t child;
int fd[2];
int ret;
if (0 != socketpair( AF_UNIX, SOCK_STREAM,0, fd))
{
printf("socketpair fail\n";
}
else
{
printf("scoketpair succ\n";
}
if( (child = fork( ) ) < 0 ) {
err_quit("fork ";
}
if( child > 0 ) { /*父进程*/
//printf("the i is %d\n", i);
close( fd[1] );
mypid[i].id = child;
mypid[i].fd= fd[0];
mypid[i].flags = IDLE;
mypid[i].cnt = 0;
return child;
}
/*子进程*/
close( fd[0] );
close(listenfd);
//dup2( fd[1], STDERR_FILENO);
//close( fd[1]);
printf("fd[1] = %d\n", fd[1]);
child_func(getpid(), i, fd[1]);
}
void child_func(pid_t pid, int id, int fd) {
int connfd, n;
char c;
char buf[MAXLINE];
for( ; ; )
{
printf("fd = %d\n", fd);
n = read_the_fd(fd, &c, 1, &connfd);
printf("read fd succ!!![id = %d][fd = %d]\n", id, connfd);
if(n <0 )
err_sys("read_fd");
again:
/*
while( (n = read(connfd, buf, sizeof(buf))) > 0 ){
write(connfd, buf ,n);
printf("%s[id = %d]\n", buf, id);
}
*/
n = read(connfd, buf, sizeof(buf));
printf("break connfd\n");
if((n < 0)&&( errno == EINTR))
goto again;
else if(n < 0)
err_sys("error");
else if(n == 0) {
close(connfd);
//printf("$$$$$$[id = %d]\n", id);
write(fd, " ", 1);
}
}
}
ssize_t write_the_fd(int fd, void *ptr, size_t nbytes, int sendfd) {
struct msghdr msg;
struct iovec iov[1];
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
int ret = 0;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS;
*((int *) CMSG_DATA(cmptr)) = sendfd;
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
ret = sendmsg(fd, &msg, 0);
perror("sendmsg");
printf("fd = %d,ret = %d\n", fd, ret);
return ret;
}
ssize_t read_the_fd(int fd, void *ptr, size_t nbytes, int *recvfd) {
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
int newfd;
union {
struct cmsghdr cm;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
struct cmsghdr *cmptr;
msg.msg_control = control_un.control;
msg.msg_controllen = sizeof(control_un.control);
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if ( (n = recvmsg(fd, &msg, 0)) <= 0)
return(n);
if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmptr->cmsg_level != SOL_SOCKET)
err_quit("control level != SOL_SOCKET");
if (cmptr->cmsg_type != SCM_RIGHTS)
err_quit("control type != SCM_RIGHTS");
*recvfd = *((int *) CMSG_DATA(cmptr));
} else
*recvfd = -1;
return(n);
}
|
|