进程间的通信之共享内存与信号量

共享内存

  • 本质:同一块物理内存映射到不同的虚拟地址空间,访问的时候和访问普通内存没什么差别。但是共享内存是进程间通信的最快的形式
  • 内存映射到共享它的进程的地址空间,那么数据间的传递不再涉及到内核。
  • 共享内存函数的介绍:https://blog.csdn.net/guoping16/article/details/6584058

  • 共享内存没有进行同步与互斥

  • 共享内存用于任意进程之间
  • 双向通信,全双工
  • 没有面向字节流,随机访问。

信号量

  • 本质:计数器(可用资源的个数,用s表示,=0则表示没有可用的资源,无等待进程)
struct semaphore
 {
     int value;  //可用资源个数
     pointer_pcb queue;
}
  • 系统中的某些资源只允许一个进程使用,这样的资源称为临界资源或者是互斥资源
用信号量实现PV操作
sem.c源代码如下:

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

union semun {

        int val; /* value for SETVAL */

        struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */

        unsigned short *array; /* array for GETALL, SETALL */

        struct seminfo *__buf; /* buffer for IPC_INFO */

        };

/***对信号量数组semnum编号的信号量做P操作***/

int P(int semid, int semnum)//这里的参数分别是信号量标识码和执行的顺序优先级

{

        struct sembuf sops={semnum,-1, SEM_UNDO};

        return (semop(semid,&sops,1));

}

/***对信号量数组semnum编号的信号量做V操作***/

int V(int semid, int semnum)

{

        struct sembuf sops={semnum,+1, SEM_UNDO};

        return (semop(semid,&sops,1));

}



int main(int argc, char **argv)

{ 

        int key ;

        int semid,ret;

        union semun arg;

        struct sembuf semop;

        int flag ;



        key = ftok("/tmp", 0x66 ) ;//获取ID

        if ( key < 0 )

        {

            perror("ftok key error") ;

            return -1 ;

        }



        semid = semget(key,1,IPC_CREAT|0600);//创建一个信号量

        if (semid == -1)

        {

                perror("create semget error");

                return ;

        }

        if ( argc == 1 )

        {

            arg.val = 1;



            ret =semctl(semid,0,SETVAL,arg);//设置0信号量的计数值为1

            if (ret < 0 )

            {

                    perror("ctl sem error");

                    semctl(semid,0,IPC_RMID,arg);

                    return -1 ;

            }

        }

        /***取0号信号量的值***/

        ret =semctl(semid,0,GETVAL,arg);

        printf("after semctl setval  sem[0].val =[%d]\n",ret);

        system("date") ;

        printf("P operate begin\n") ;

        flag = P(semid,0)  ;   //p操作

        if ( flag )

        {

            perror("P operate error") ;

            return -1 ;

        }

        printf("P operate end\n") ;

        ret =semctl(semid,0,GETVAL,arg);

        printf("after P sem[0].val=[%d]\n",ret);

        system("date") ;

        if ( argc == 1 )

        {

            sleep(120) ;

        }

        printf("V operate begin\n") ;

    if (V(semid, 0) < 0)     //v操作

        {

            perror("V operate error") ;

            return -1 ;

        }

        printf("V operate end\n") ;

        ret =semctl(semid,0,GETVAL,arg);

        printf("after V sem[0].val=%d\n",ret);

        system("date") ;

        if ( argc >1 )

        {

            semctl(semid,0,IPC_RMID,arg);

        }



        return 0 ;

}
  • 可用于任意的进程,生命周期随内核

猜你喜欢

转载自blog.csdn.net/Ning_zhi_t/article/details/81351893