论坛徽章: 0
5 可用积分
用fork创建含有4个子进程的进程链,多个进程对一个缓冲区进行并发访问,我用信号量对一个缓冲区进行互斥保护.
父进程调用wait,一直等到子进程执行完毕,然后删除信号量.代码如下:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define BUF_SIZE 256
#define PERMS (S_IRUSR | S_IWUSR)
pid_t RWait( int* stat_loc )
{
pid_t ret;
while( ( -1 == ( wait( stat_loc ) ) ) && ( EINTR == errno ) );
return ret;
}
int InitElement( int aSemId, int aSemNum, int aSemValue )//初始化一个信号量的值
{
union semun
{
int val;
struct semid_ds* buf;
unsigned short* array;
}arg;
arg.val = aSemValue;
return semctl( aSemId, aSemNum, SETVAL, arg );
}
int RmSem( int aSemId )//删除一个信号量
{
return semctl( aSemId, 0, IPC_RMID );
}
void SetSemBuf( struct sembuf* aBuf, int aNum, int aOp, int aFlg )//给一个struct sembuf数组进行初始化
{
aBuf->sem_num = aNum;
aBuf->sem_op = aOp;
aBuf->sem_flg = aFlg;
}
int RSemop( int aSemId, struct sembuf* aSops, int aNsops )//信号量操作
{
int err;
while( ( -1 == ( err = semop( aSemId, aSops, aNsops ) ) )
&& ( EINTR == errno ) );
return err;
}
int main( int argc, char** argv )
{
char buf[BUF_SIZE];
char* bufP = NULL;
pid_t chdPid;
int semId;
int i;
int j;
int err;
int KDelay = 9;
struct sembuf semSignal[1];
struct sembuf semWait[1];
buf[BUF_SIZE-1] = '\0';
if( -1 == ( semId = semget( IPC_PRIVATE, 1, PERMS ) ) )//创建一个信号量
{
perror( "semget error:\n" );
exit( EXIT_FAILURE );
}
SetSemBuf( semWait, 0, -1, 0 );//初始化semWait sembuf,用于semop的lock操作
SetSemBuf( semSignal, 0, 1, 0 );//初始化semSignal sembuf,用于semop的unlock操作
if( -1 == InitElement( semId, 0, 1 ) )//将信号量的值初始化为1
{
perror( "InitElement error:\n" );
RmSem( semId );
exit( EXIT_FAILURE );
}
for( i=0; i<4; i++ )//创建含有4个子进程的进程链
{
if( 0 != ( chdPid = fork() ) )
{
break;
}
}
snprintf( buf,
BUF_SIZE,
"Id:%ld PId:%ld chdId:%ld\n",
(long)getpid(),
(long)getppid(),
(long)chdPid );
bufP = buf;
if( ( -1 == ( err = RSemop( semId, semWait, 1 ) ) ) && ( 1<i ) )//用semop对其他进程进行lock操作
{
fprintf( stderr, "%ld Failed to lock semId:%s\n",
(long)getpid(),
strerror( err ) );
return EXIT_FAILURE;
}
else if( !err )
{
while( '\0' != *bufP )//输出buf
{
fputc( *bufP, stderr );
bufP++;
for( j=0; j<KDelay; j++ );
}
if( -1 == ( err = RSemop( semId, semSignal, 1 ) ) )//用semop对其他进程进行unlock操作,释放信号量.
{
fprintf( stderr, "%ld Failed to unlock semId:%s\n",
(long)getpid(),
strerror( err ) );
}
}
if( ( -1 == RWait( NULL ) ) && ( ECHILD != errno ) )//等待所有的子进程
{
fprintf( stderr, "%ld Failed to wait:%s\n",
(long)getpid(),
strerror( errno ) );
}
if( ( -1 == ( err = RmSem( semId ) ) ) && ( 1 == i ) )//删除信号量
{
fprintf( stderr, "%ld Failed to clean up:%s\n",
(long)getpid(),
strerror( err ) );
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
程序结果大致为(每次结果不一样):
Id:3606 PId:3605 chdId:0
3604 Failed to lock semId:Unknown error 4294967295
3605 Failed to lock semId:Unknown error 4294967295
3603 Failed to wait:Invalid argument
3603 Failed to clean up:Unknown error 4294967295
3602 Failed to wait:Invalid argument
发现第一个子进程对信号量进行lock操作就失败了.
我对"Unknown error 4294967295"google了一把,
发现chinaunix以前也讨论这个错误,貌似是内核错误.
我使用的是fedora10,内核为:2.6.27.21
是我代码本身有问题,还真的是内核问题,
怎样解决了?谢谢!!!!!!!!!!!!
我来回答