QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 805|回复: 1

如何使用非阻塞的信号量

[复制链接]
发表于 2004-6-11 10:35:14 | 显示全部楼层 |阅读模式
我这里有一个问题.一个共享资源在同一时刻只能由一个访问者,用信号量实现.但是如果这个资源正在被访问,另外一个立即退出.
请问应该怎么做?
我这里的代码如下,请问应该怎样修改
[code:1]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>

#include <linux/types.h>
#include <linux/sem.h>
#include <linux/ipc.h>

#include <wait.h>
#include <time.h>

#define HT_HONEYPOT_PORT         5320
#define HT_MAX_CLIENT_NUM         1

#define SEM_ID 250

int sem_lock(int sem_set_id)
{
        struct sembuf sem_op;
        sem_op.sem_num = 0;
        sem_op.sem_op = -1;
        sem_op.sem_flg = IPC_NOWAIT;
        return semop(sem_set_id, &sem_op, 1);
}

int sem_unlock(int sem_set_id)
{
        struct sembuf sem_op;
        sem_op.sem_num = 0;
        sem_op.sem_op = 1;
        sem_op.sem_flg = 0;
        return semop(sem_set_id, &sem_op, 1);
}

int main(void)
{
        int listen_fd, connect_fd;
        struct sockaddr_in server_addr;
        struct sockaddr_in client_addr;
        int rc;       
       
        int sin_size;
       
        char hello[] = "Hello! Are You Fine?";
       
        int sem_set_id;
        union semun sem_val;
        pid_t pid;

        sem_set_id = semget(SEM_ID, 1, IPC_CREAT|0600);
        if(sem_set_id == -1)
        {
                perror("Error: semget()");
                exit(1);
        }
       
        sem_val.val = 1;
        if( semctl(sem_set_id, 0, SETVAL, sem_val) == -1)
        {
                perror("main: semctl()");
                exit(1);
        }
       
        if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
                perror("Error: socket()");
                exit(1);
        }

        bzero(&server_addr, sizeof(struct sockaddr_in));
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        server_addr.sin_port = htons(HT_HONEYPOT_PORT);
       
        if(bind(listen_fd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
        {
                perror("Bind error\n");
                exit(1);
        }

        if(listen(listen_fd, 5) == -1)
        {
                perror("Listen Error");
                exit(1);
        }       
       
        while(1)
        {
                sin_size = sizeof(struct sockaddr_in);
                if((connect_fd = accept(listen_fd, (struct sockaddr *)(&client_addr), &sin_size)) == -1)
                {
                        perror("Accept error");
                        exit(1);
                }
               
                fprintf(stderr, "Server get connection from %s\n",
                                                inet_ntoa(client_addr.sin_addr));
               
                if( (pid = fork()) == 0)
                {
                        close(listen_fd);
                        if(sem_lock(sem_set_id) != EAGAIN)
                        {
                                int i;
                                for(i = 0; i < 10; i++)
                                {
                                        sleep(2);
                                        if(write(connect_fd, hello, strlen(hello)) == -1)
                                        {
                                                fprintf(stderr, "Write error");
                                                close(connect_fd);
                                                sem_unlock(sem_set_id);
                                                exit(1);
                                        }
                                }
                                close(connect_fd);
                                sem_unlock(sem_set_id);
                                exit(0);
                        }
                        else
                        {
                                fprintf(stdout, "Some Body have conncected\n");
                                close(connect_fd);
                        }                                       
                }
        }
        close(listen_fd);
        return 0;
}

[/code:1]
发表于 2004-6-11 11:50:43 | 显示全部楼层
你已经设置了非阻塞方式,但是在你判断semop()返回值得时候,应该是判断返回值是否为-1,再判断errno是否等于EAGAIN,程序修改如下:
[code:1]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>

#include <linux/types.h>
#include <linux/sem.h>
#include <linux/ipc.h>

#include <wait.h>
#include <time.h>

#define HT_HONEYPOT_PORT    5320
#define HT_MAX_CLIENT_NUM    1

#define SEM_ID 250

int sem_lock(int sem_set_id){
    struct sembuf sem_op;
    sem_op.sem_num = 0;
    sem_op.sem_op =  - 1;
    sem_op.sem_flg = IPC_NOWAIT;
    return semop(sem_set_id, &sem_op, 1);
}

int sem_unlock(int sem_set_id){
    struct sembuf sem_op;
    sem_op.sem_num = 0;
    sem_op.sem_op = 1;
    sem_op.sem_flg = 0;
    return semop(sem_set_id, &sem_op, 1);
}

int main(void){
    int listen_fd, connect_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int rc;

    int sin_size;

    char hello[] = "Hello! Are You Fine?";

    int sem_set_id;
    union semun sem_val;
    pid_t pid;

    sem_set_id = semget(SEM_ID, 1, IPC_CREAT | 0600);
    if (sem_set_id ==  - 1){
        perror("Error: semget()");
        exit(1);
    }

    sem_val.val = 1;
    if (semctl(sem_set_id, 0, SETVAL, sem_val) ==  - 1){
        perror("main: semctl()");
        exit(1);
    }

    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) ==  - 1){
        perror("Error: socket()");
        exit(1);
    }

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(HT_HONEYPOT_PORT);

    if (bind(listen_fd, (struct sockaddr*)(&server_addr), sizeof(struct
        sockaddr)) ==  - 1){
        perror("Bind error\n");
        exit(1);
    }

    if (listen(listen_fd, 5) ==  - 1){
        perror("Listen Error");
        exit(1);
    }

    while (1){
        sin_size = sizeof(struct sockaddr_in);
        if ((connect_fd = accept(listen_fd, (struct sockaddr*)(&client_addr),
            &sin_size)) ==  - 1){
            perror("Accept error");
            exit(1);
        }

        fprintf(stderr, "Server get connection from %s\n", inet_ntoa
            (client_addr.sin_addr));

        if ((pid = fork()) == 0){
            close(listen_fd);
            if (sem_lock(sem_set_id) !=  - 1){   //这里应该判断是否等于-1
                int i;
                for (i = 0; i < 10; i++){
                    sleep(2);
                    if (write(connect_fd, hello, strlen(hello)) ==  - 1){
                        fprintf(stderr, "Write error");
                        close(connect_fd);
                        sem_unlock(sem_set_id);
                        exit(1);
                    }
                }
                close(connect_fd);
                sem_unlock(sem_set_id);
                exit(0);
            }
            else{
                if (errno == EAGAIN){    //然后再判断errno是否等于EAGAIN
                    fprintf(stdout, "Some Body have conncected\n");
                    close(connect_fd);
                    exit(0);
                }
            }
        }
    }
    close(listen_fd);
    return 0;
}
[/code:1]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-8 05:51 , Processed in 0.041772 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表