免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3645 | 回复: 2
打印 上一主题 下一主题

信号量lock问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-16 22:11 |只看该作者 |倒序浏览
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

是我代码本身有问题,还真的是内核问题,
怎样解决了?谢谢!!!!!!!!!!!!

论坛徽章:
0
2 [报告]
发表于 2009-11-16 22:41 |只看该作者

  1. pid_t RWait( int* stat_loc )
  2. {
  3.         pid_t ret;

  4.         while( (  -1 == ( wait( stat_loc ) ) ) && ( EINTR == errno ) );

  5.         return ret;
  6. }
复制代码

这一段,ret没有初始化,后续代码也没有对它赋值

论坛徽章:
0
3 [报告]
发表于 2009-11-16 23:04 |只看该作者
原帖由 churchmice 于 2009-11-16 22:41 发表

pid_t RWait( int* stat_loc )
{
        pid_t ret;

        while( (  -1 == ( wait( stat_loc ) ) ) && ( EINTR == errno ) );

        return ret;
}

这一段,ret没有初始化,后续代码也没有 ...


谢谢!!!!
感谢大哥找出这个错误,我修改后的代码:
pid_t RWait( int* stat_loc )
{
        pid_t ret;

        while( (  -1 == ( ret =  wait( stat_loc ) ) ) && ( EINTR == errno ) );

        return ret;
}

但还是发生"Unknown error 4294967295"的错误
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP