高手赐教

zhangjingyuhua 2009-02-06 03:06:37
我现在遇到这样的情况:

data= sock.recv()//socket 通信
fifoname = data+".rep"
if access(fifoname, F_OK)
{ infifo = open(fifoname , 'w')
write(infifo, data, 556)
close(infifo);
}
else
{
mkfifo(fifoname )
pid = fork()
if pid = 0
{
child_func()
}
if pid > 0
infifo = open(fifoname , 'w')
write(infifo, data, 556)
close(infifo);
}

child_func()
{
while 1:
outinfifo = open(fifoname , r)
r, w, e = select([outinfifo ], [], [])
if len(r) == 1:
ss = read(outinfifo )
}

现在出现的问题:
1:多个客户同时送同样的数据时,如果是第一次由socket接收时,父进程可以写,但子进程能把父进程写入的数据一次读取
2:当客户端第二次连接时,送同样的数据时,父进程只能写一次数据
3:过一段时间,子进程挂掉.

我想解决的问题:
1:父进程写一次,子进程读一次
2:子进程如何不能挂掉
...全文
268 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
weidong0210 2009-02-09
  • 打赏
  • 举报
回复
up
zhangjingyuhua 2009-02-09
  • 打赏
  • 举报
回复
我觉得[du51]的想法和流程都很清晰,但我的要求,还有一点出入:
我需要的网络模型:
子进程
|
|
管道文件
|
/ \
C1 C2
C1,C2负责写,子进程负责读.
管道只能写入的数据大于PIPE_BUF才不是原子操作,需不需要互斥?
lzh9955 2009-02-07
  • 打赏
  • 举报
回复
up
herman~~ 2009-02-07
  • 打赏
  • 举报
回复
MARK
du51 2009-02-06
  • 打赏
  • 举报
回复
好久没写LINUX程序..试了一下..还可以.
把PTHREAD搬到了进程间..不是很好..
可以试下信号灯..呵呵.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>

#define FIFO_FILE ".fifo_test"

void *g_addr;
int *g_sign;

pthread_mutex_t *p_mutex;
pthread_cond_t *p_cond_full;
pthread_cond_t *p_cond_empty;

/*从FD读N个字节,成功返回n>=0 不成功-1*/
static ssize_t _pipe_readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;


ptr = (char*)vptr;
nleft = n;
while (nleft > 0)
{
nread = read(fd, ptr, nleft);
if (nread < 0)
{
if (errno == EINTR)
{
continue;
}
else if (errno == EAGAIN || errno == EWOULDBLOCK)
{
continue;
}
else
{
return - 1;
}
}
else if (nread == 0)
{
//closed
break;
}

nleft -= nread;
ptr += nread;
}

return (n - nleft);
}

/*写FD N个字节,成功返回n>=0 不成功-1*/
static ssize_t _pipe_writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;

ptr = (char*)vptr;
nleft = n;
while (nleft > 0)
{
nwritten = write(fd, ptr, nleft);
if (nwritten <= 0)
{
if (errno == EINTR)
{
continue;
}
else if (errno == EAGAIN || errno == EWOULDBLOCK)
{
continue;
}
else
{
return - 1;
}
}

nleft -= nwritten;
ptr += nwritten;
}

return n;
}


int set_gmem(void **addr)
{
int fd;

fd = open("/dev/zero", O_RDWR);
if (fd == -1)
{
perror("open");
return -1;
}

*addr = mmap(0, sizeof(pthread_mutex_t) + 2 * sizeof(pthread_cond_t) + sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

close(fd);

if (*addr == MAP_FAILED)
{
perror("mmap");
return - 1;
}
return 0;
}





void go_over(int sig)
{
fprintf(stdout, "\n%d sig %d now go over!\n", sig, getpid());
unlink(FIFO_FILE);
pthread_mutex_destroy(p_mutex);
pthread_cond_destroy(p_cond_empty);
pthread_cond_destroy(p_cond_full);
munmap(g_addr, sizeof(pthread_mutex_t) + 2 * sizeof(pthread_cond_t) + sizeof(int));
exit(0);
}

int main()
{
int fd;
pid_t pid;
int sig;
char l_buff[48];
pthread_condattr_t condattr;
pthread_mutexattr_t mutexattr;

/*清信号,留下结束程序用*/
for (sig = 1; sig <= SIGRTMAX; sig ++)
{
if (sig != SIGINT && sig != SIGUSR2)
{
signal(sig, SIG_IGN);
}
}

signal(SIGINT, go_over);


if (set_gmem(&g_addr) == -1)
return -1;

p_mutex = (pthread_mutex_t *)g_addr;
p_cond_full = (pthread_cond_t *)(p_mutex + 1);
p_cond_empty = p_cond_full + 1;
g_sign = (int *)(p_cond_empty + 1);

pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);

pthread_mutex_init(p_mutex, &mutexattr);
pthread_cond_init(p_cond_full, &condattr);
pthread_cond_init(p_cond_empty, &condattr);



unlink(FIFO_FILE);
if (mkfifo(FIFO_FILE, 0777) != 0)
{
perror("mkfifo");
return -1;
}

*g_sign = 0;



pid = fork();

if (pid < 0)
{
perror("fork");
return -1;
}
else if (pid > 0)
{
fd = open(FIFO_FILE, O_WRONLY);
if (fd < 0)
{
perror("open");
return -1;
}



for (;;)
{
pthread_mutex_lock(p_mutex);

while (*g_sign != 0)
{
pthread_cond_wait(p_cond_empty, p_mutex);
}

_pipe_writen(fd, "Hello World", 11);
fprintf(stdout, "%d write Hello World\n", getpid());

*g_sign = 1;
pthread_cond_broadcast(p_cond_full);

pthread_mutex_unlock(p_mutex);

}
close(fd);
}
else
{
fd = open(FIFO_FILE, O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}


for (;;)
{
pthread_mutex_lock(p_mutex);

while (*g_sign != 1)
{
pthread_cond_wait(p_cond_full, p_mutex);
}

memset(l_buff, 0, sizeof(l_buff));
_pipe_readn(fd, l_buff, 11);
fprintf(stdout, "%d read %s\n", getpid(), l_buff);

*g_sign = 0;
pthread_cond_broadcast(p_cond_empty);

pthread_mutex_unlock(p_mutex);
}
close(fd);
}

return 0;
}
lbjfeng 2009-02-06
  • 打赏
  • 举报
回复
帮忙顶
zhangjingyuhua 2009-02-06
  • 打赏
  • 举报
回复
不知道有没有高手啊,现在子进程挂掉的问题被搞定了.
但在子进程不能阻塞,老是在轮询,有什么办法.
阻塞住啊.
出现不断的轮询的原因是这样的:
当有客户第一次连接,发送数据,然后主进程创建有名管道.
同时把数据写入管道.那么子进程能读取数据.然而父进程很长时间
才进行第二次接收数据,那么这段时间子进程就一直在轮询.
按照select是应该把读集合给清除,但是清除了.父进程写入的数据
开始创建的子进程就没有办法读取了
ysuliu 2009-02-06
  • 打赏
  • 举报
回复
1, 同步是肯定要加的,要不没办法。
2, 挂掉就只有单步跟一下了,看看问题在哪。如果有dump文件也可以拿来分析一下啊。。
oyljerry 2009-02-06
  • 打赏
  • 举报
回复
父进程,子进程之间要做进程同步等....
子进程挂掉可能程序代码有问题,引起异常了,可以挂掉的时候调式,看什么引起的
eagerle01 2009-02-06
  • 打赏
  • 举报
回复
sf

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧