• linux第11天 共享内存和信号量


     今天主要学习了共享内存和信号量

    在此之前,有个管道问题

    ls | grep a

    整句话的意思是将ls输出到管道的写端,而流通到另一端的读端,grep a则是从管道的读端读取相关数据,再做筛选

    共享内存

    int shmget(key_t key, size_t size, int flag);

    key: 标识符的规则
    size:共享存储段的字节数
    flag:读写的权限 0666 | O_CREAT
    返回值:成功返回共享存储的id,失败返回-1

    shmat
    void *shmat(int shmid, const void *shmaddr, int flag);
    shmid:共享存储的id
    shmaddr:一般为0,表示连接到由内核选择的第一个可用地址上,否则,如果flag没有指定SHM_RND,则连接到addr所指定的地址上,如果flag为SHM_RND,则地址取整
    flag:如前所述,一般为0
    返回值:如果成功,返回共享存储段地址,出错返回-1

    shmaddr为NULL,核心自动选择一个地址
    shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
    shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
    shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

    shmdt

    行为与shmat相反,取消共享内存映射

    shmctl函数
      功能:用于控制共享内存
      原型
      int shmctl(int shmid, int cmd, struct shmid_ds  *buf);
      参数
      shmid:由shmget返回的共享内存标识码
      cmd:将要采取的动作(有三个可取值)
      buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
      返回值:成功返回0;失败返回-1

    共享内存的创建与操作

    	int shmid = shmget(0x159357, 4, 0666 | IPC_CREAT);	
    	if (shmid < 0)
    		perror("shmget");
    
    	void *p = NULL;
    	p = shmat(shmid, NULL, 0);
    	(*(int *)p) = 0;
    		
    	shmdt(p);
    

      

    信号量 

    信号量可以看成一个结构体,里面包含两个字段同数据.

    1.可以使用的资源数据.当资源数用完,没有资源释放,再次访问资源内核将阻塞进程

    2.被阻塞的进程队列.

    struct semaphore
    {
      int value;
      pointer_PCB queue;
    }

    信号量值含义
    S>0:S表示可用资源的个数
    S=0:表示无可用资源,无等待进程
    S<0:|S|表示等待队列中进程个数

    P原语
    P(s)
    {
      s.value = s.value--;
      if (s.value< 0)
      {
        该进程状态置为等待状状态
        将该进程的PCB插入相应的等待队列s.queue末尾
      }
    }

    V原语
    V(s)
    {
      s.value = s.value++;
      if (s.value< =0)
      {
        唤醒相应等待队列s.queue中等待的一个进程
        改变其状态为就绪态
        并将其插入就绪队列
      }
    }

    semget函数
    功能:用来创建和访问一个信号量集
    原型
    int semget(key_t key, int nsems, int semflg);
    参数
    key: 信号集的名字
    nsems:信号集中信号量的个数
    semflg: 由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
    返回值:成功返回一个非负整数,即该信号集的标识码;失败返回-1

    shmctl函数
    功能:用于控制信号量集
    原型
    int semctl(int semid, int semnum, int cmd, ...);
    参数
    semid:由semget返回的信号集标识码
    semnum:信号集中信号量的序号
    cmd:将要采取的动作(有三个可取值)
    最后一个参数根据命令不同而不同
    返回值:成功返回0;失败返回-1

    semop函数
    功能:用来创建和访问一个信号量集
    原型
    int semop(int semid, struct sembuf *sops, unsigned nsops);
    参数
    semid:是该信号量的标识码,也就是semget函数的返回值
    sops:是个指向一个结构数值的指针
    nsops:信号量的个数
    返回值:成功返回0;失败返回-1

    semop函数续
    sembuf结构体:
    struct sembuf {
      short sem_num;
      short sem_op;
      short sem_flg;
    };
    sem_num是信号量的编号。
    sem_op是信号量一次PV操作时加减的数值,一般只会用到两个值,一个是“-1”,也就是P操作,等待信号量变得可用;另一个是“+1”,也就是我们的V操作,发出信号量已经变得可用
    sem_flag的两个取值是IPC_NOWAIT或SEM_UNDO,一般取0

    封装好的信号操作函数

    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
                                   (Linux-specific) */
    };
    
    
    int semCreateOrGet(key_t key)
    {
    	int semid = 0;
    	semid = semget(key, 1, 0666 | IPC_CREAT);
    	if (semid < 0)
    		ERR_EXIT("semget");
    		
    	return semid;
    }
    
    int semSetValue(int semid, int val)
    {
    	int ret = 0;
    	union semun su;
    	su.val = val;
    	ret = semctl(semid, 0, SETVAL, su);
    	return ret;
    	
    }
    
    
    int semGetValue(int semid)
    {
    	int ret = 0;
    	union semun su;
    	ret = semctl(semid, 0, GETVAL, su);
    	printf("目前资源数为%d
    ", su.val);
    	return ret;
    	
    }
    
    int sem_p(int semid)
    {
    	int ret = 0;
    	struct sembuf sbuf = { 0, -1, 0 };
    	ret  = semop(semid, &sbuf, 1);
    	return ret;
    }
    
    int sem_v(int semid)
    {
    	int ret = 0;
    	struct sembuf sbuf = { 0, 1, 0 };
    	ret  = semop(semid, &sbuf, 1);
    	return ret;
    }
    

      

  • 相关阅读:
    mysql各个版本下载地址
    hadoop-0.20.2完全分布式集群
    04_Spring中使用Quartz
    03_CronTrigger
    02_SimpleTrigger
    02_ActiveMQ入门
    01_JMS概述
    01_Quartz基础结构
    Java开发高性能网站需要关注的事
    06_Jedis完成MySQL的条件查询案例
  • 原文地址:https://www.cnblogs.com/c-slmax/p/5277173.html
Copyright © 2020-2023  润新知