• 17.信号量同步编程


    17.信号量同步编程

    进程同步:

    一组并发进程进行互相合作、互相等待,使得各进程按一定的顺序执行的过程称为进程间的同步。

    生产者:1.创建文件。2.往文件写内容。(中间有sleep)。

    进程同步中经典的实例:生产者与消费者的问题。

    Producer.c:

    #include <stdio.h>

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <unistd.h>

    #include <fcntl.h>

    void main(){

        int fd;

        //create product

        fd = open("/home/zhu",O_RDWR | O_CREAT,0777);

        sleep(20);

        //completing product

        write(fd,"the product is complete!",24);

        close(fd);

    }

    consumer.c:

    #include <stdlib.h>

    #include <stdio.h>

    void main(){

        //take away product

        system("cp /home/zhu ./");

    }

    运行的结果:

    我们看到产品是生产出来了,可是一个半成品,里面啥内容都没。这是因为我们的生产者,在生产东西的时候,还没完成,中途有事出去,然后消费者不知道产品还没完成就取走了。

        

    这个问题和前面的信号量互斥有点相似:我们把信号量的初始值设置为0(与互斥不同),然后我们生产者不用获取信号量,他需要的是释放信号量,就是他完成生产一件产品之后要释放信号量。切记是在生产好了一件产品后释放信号量。就是生产者不获取信号量,只释放信号量。由于我们信号量的初始值是0,无法获取信号量,就是消费者不能拿走产品,因为信号量为0,这就确保了产品只有完成才能让消费者拿走,注意的是,我们的消费者不用释放信号量。

    运行的结果:

    Productor1.c:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <stdlib.h>

    #include <sys/sem.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include <unistd.h>

    void main(){

        int fd;

        key_t key;

        int semid;

        struct sembuf sops;

        key = ftok("/home",2);

        

        //create semaphore

        semid = semget(key,1,IPC_CREAT);

        semctl(semid,0,SETVAL,0);

        //create product

        fd = open("/home/zhu",O_RDWR | O_CREAT,0777);

        sleep(20);

        //completing product

        write(fd,"the product is complete!",24);

        //free

        sops.sem_num = 0;

        sops.sem_op = 1;

        sops.sem_flg = SEM_UNDO;

        semop(semid,&sops,1);

        close(fd);

    }

    consumer1.c:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <stdlib.h>

    #include <sys/sem.h>

    void main(){

        key_t key;

        int semid;

        struct sembuf sops;

        key = ftok("/home",2);

        

        //create semaphore

        semid = semget(key,1,IPC_CREAT);

        //get semaphore

        sops.sem_num = 0;

        sops.sem_op = -1;

        sops.sem_flg = SEM_UNDO;//free

        semop(semid,&sops,1);

        //take product

        system("cp /home/zhu ./");

    }

    运行的结果:

    拿走成功:

    我们就实现了只有生产者生产好了产品,消费者才能拿走的机制。

    我们在消费者程序中用到system函数:

    man 3 system:的信息:

    NAME

    system - execute a shell command

    SYNOPSIS

    #include <stdlib.h>

    int system(const char *command);

    DESCRIPTION

    system() executes a command specified in command by calling /bin/sh -c command,

    and returns after the command has been completed. During execution of the com-

    mand, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

    RETURN VALUE

    The value returned is -1 on error (e.g. fork(2) failed), and the return status

    of the command otherwise. This latter return status is in the format specified

    in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In

    case /bin/sh could not be executed, the exit status will be that of a command

    that does exit(127).

    If the value of command is NULL, system() returns non-zero if the shell is

    available, and zero if not.

    system() does not affect the wait status of any other children.

    CONFORMING TO

    C89, C99, POSIX.1-2001.

    NOTES

    If the _XOPEN_SOURCE feature test macro is defined, then the macros described in

    wait(2) (WEXITSTATUS(), etc.) are made available when including <stdlib.h>.

    As mentioned, system() ignores SIGINT and SIGQUIT. This may make programs that

    call it from a loop uninterruptible, unless they take care themselves to check

    the exit status of the child. E.g.

    while (something) {

    int ret = system("foo");

    if (WIFSIGNALED(ret) &&

    (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))

    break;

    }

    Do not use system() from a program with set-user-ID or set-group-ID privileges,

    because strange values for some environment variables might be used to subvert

    system integrity. Use the exec(3) family of functions instead, but not exe-

    clp(3) or execvp(3). system() will not, in fact, work properly from programs

    with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash

    version 2, since bash 2 drops privileges on startup. (Debian uses a modified

    bash which does not do this when invoked as sh.)

    In versions of glibc before 2.1.3, the check for the availability of /bin/sh was

    not actually performed if command was NULL; instead it was always assumed to be

    available, and system() always returned 1 in this case. Since glibc 2.1.3, this

    check is performed because, even though POSIX.1-2001 requires a conforming

    implementation to provide a shell, that shell may not be available or executable

    if the calling program has previously called chroot(2) (which is not specified

    by POSIX.1-2001).

    It is possible for the shell command to return 127, so that code is not a sure

    indication that the execve(2) call failed.

    SEE ALSO

    sh(1), signal(2), wait(2), exec(3)

    COLOPHON

    This page is part of release 3.22 of the Linux man-pages project. A description

    of the project, and information about reporting bugs, can be found at

    http://www.kernel.org/doc/man-pages/.

  • 相关阅读:
    HTML5 Video/Audio播放本地文件
    jquery 美化弹出提示 漂亮的Dialog 对话框
    JavaScript中变量、作用域、内存问题
    利用nethogs查看哪些进程占用网络带宽
    Dell服务器硬件监控,使用omreport出现object not found 错误解决
    filebeat收集nginx的json格式日志
    利用logrotate切割nginx的access.log日志
    Linux下单机部署ELK日志收集、分析环境
    linux开启Rsyslog服务收集日志
    mysql占用磁盘IO过高的解决办法
  • 原文地址:https://www.cnblogs.com/FORFISH/p/5188659.html
Copyright © 2020-2023  润新知