关于多进程同步问题求助

发布于 2022-07-23 02:54:08 字数 9138 浏览 8 评论 1

程序产生两个进程,childA,childB两个进程分别使用管道进行通信,childA对管道写数据childB对管道读数据!父进程利用pause函数进入等待状态,然后利用signal来获取子进程的退出!代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/sem.h>

#define SEMPERM                0600 //信号量创建后的访问许可权
typedef union _semun{
        int val;
        struct semid_ds *buf;
        ushort *array;
}semun;

typedef void Sigfunc(int);
int semids;

void childA(int *fd,int s_key)
{
        int data = 1;        
        close(fd[0]);
        for(;data < 20;data++){
                p(s_key); //P操作
                fprintf(stderr,"run child A %d n",data);
                write(fd[1],(char*)&data,sizeof(int));
        }
        exit(1);
}

Sigfunc *signal(int singno,Sigfunc *func)
{
        struct sigaction atc,oatc;
        atc.sa_handler = func;
        sigemptyset(&atc.sa_mask);
        atc.sa_flags = 0;
        if(sigaction(singno,&atc,&oatc) < 0)
                return (SIG_ERR);
        return (oatc.sa_handler);
}
Sigfunc *Signal(int signalno,Sigfunc *func)
{

        Sigfunc *sigfunc;
        if( (sigfunc = signal(signalno,func)) == SIG_ERR)
                fprintf(stderr,"Signal error n");
        
        return (sigfunc);
               
}
void childB(int *fd,int s_key)
{
        int re_data = 1;
        int a = 0;
        fd_set reads;

        close(fd[1]);
        FD_ZERO(&reads);
        FD_SET(fd[0],&reads);

        while(a++ < 19){
        select(fd[0]+1,&reads,NULL,NULL,NULL);
                if(FD_ISSET(fd[0],&reads)){
                read(fd[0],(char *)&re_data,sizeof(int));
                fprintf(stderr,"Out data %d %dn",re_data,a);
                sleep(a);
                v(s_key); //v 操作
                }
        }
        exit(2);

}
int initsem(key_t semkey) //创建并初始化信号量
{
        int status = 0,semid;
        
        if((semid = semget(semkey,1,SEMPERM|IPC_CREAT|IPC_EXCL)) == -1){
                perror("Sem error n ");
                if(errno == EEXIST)
                        semid = semget(semkey,1,0);
        }else{
                semun arg;
                arg.val = 1;
                status = semctl(semid,0,SETVAL,arg);         
        }
        if(semid == -1 || status == -1){
                perror("Init sem error n");
        }

        return semid;
        
        
}
int p(int semid)
{
        struct sembuf p_buf;
        p_buf.sem_num = 0;
        p_buf.sem_op = -1;
        p_buf.sem_flg = SEM_UNDO;
        if(semop(semid,&p_buf,1) == -1){
                perror("P(semid)faild");
                exit(1);
        }
        return (0);
}
int v(int semid)
{
        struct sembuf v_buf;
        v_buf.sem_num = 0;
        v_buf.sem_op = 1;
        v_buf.sem_flg = SEM_UNDO;
        if(semop(semid,&v_buf,1) == -1){
                perror("V(semid failed ");
                exit(1);        
        }
        return (0);        
}
static void sig_cld(int signo)
{
        pid_t pid;
        int status;
        fprintf(stderr,"SIGCLD received n ");
        while((pid = waitpid(-1,&status,WNOHANG)) > 0){  //等待子进程退出
                                        //没有信号量操作时候可以成功等待所有子进程退出
                printf("pid =%d n",pid);
        }
}
        
int main()
{
        int pipe_fd[2];
        pid_t pid;
        key_t skey;
        skey = 0x1833;
        
        pipe(pipe_fd);
        semids = initsem(skey);        
        signal(SIGCHLD,sig_cld);
        pid = fork();
        if(pid == 0){
                childB(pipe_fd,semids); //创建进程B
        }
        pid = -1;
        pid = fork();
        if(pid == 0){
                childA(pipe_fd,semids); //创建进程A 先创建进程B进行读操作后创建进程A进行写操作
        }

        pause(); //等待状态
        printf("parent out n");
        exit(1);
}

现在产生两个很麻烦的问题,第一:父进程无法等待所有子进程退出后就自己退出了!第二:信号量第一次创建后,程序退出在重启动后报错,信号量已经存在!也就是这个程序无法自己释放信号量!

请问这些问题如何解决呢??伤脑筋啊!~~~

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白芷 2022-07-23 18:42:55

1. signal函数是edge triggered吧,在信号的处理函数中截获到信号后,如果不重新设置该信号的处理函数,系统就会设置成系统默认的处理函数。
2. 信号量的可以设置成让程序退出系统就自动释放的。man一下吧。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文