`
cuiyadll
  • 浏览: 201305 次
文章分类
社区版块
存档分类
最新评论

一个包含了信号、信号量、共享内存的例子(转)

c 
阅读更多
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHMKEY1 (key_t)0x10
#define SHMKEY2 (key_t)0x15

#define SEMKEY  (key_t)0x20

#define SIZ 5*BUFSIZ


#define IFLAGS (IPC_CREAT|IPC_EXCL)
#define ERR ((struct databuf*)-1)
//p1,v1是针对第一个信号进行的操作
struct sembuf p1 = {0, -1, 0};
struct sembuf v1 = {0, 1, 0};
//p2,v1是针对第二个信号进行的操作
struct sembuf p2 = {1, -1, 0};
struct sembuf v2 = {1, 1, 0};
//表示两个内存共享区和一个信号量集合
static int shmid1, shmid2, semid;
//作为暂时存放数据的结构体
struct databuf
{
    int d_nread;
    char d_buf[SIZ];
};


void fatal(char *mes)
{
      perror(mes);
      exit (1);
}
/**创建两个共享内存,并且分别shmat给两个参数*/
void getshm (struct databuf **p1, struct databuf **p2)
{      //创建共享内存
      if ((shmid1=shmget(SHMKEY1, sizeof(struct databuf), 0600|IFLAGS)) < 0)
      {
        fatal ("shmget");
      }

      if ((shmid2=shmget(SHMKEY2, sizeof(struct databuf), 0600|IFLAGS)) < 0)
      {
        fatal ("shmget");
      }
      //映射
      if ((*p1=(struct databuf*)(shmat(shmid1, 0, 0))) == ERR)
      {
        fatal("shmat");
      }

      if((*p2=(struct databuf*)(shmat(shmid2, 0, 0))) == ERR)
      {
        fatal("shmat");
      }

}

int getsem()
{
         //获取一个长度为2的信号量集合;
          if ((semid=semget(SEMKEY, 2, 0600|IFLAGS)) < 0)
          {
          fatal("segmet");
          }
          //初始化信号量,假定第一个信号灯没有资源
          if (semctl(semid, 0, SETVAL, 0) < 0)
          {
           fatal ("semctl");
          }
          //第二个有信息,如果两个信号都没有资源,将会出现死锁
          //书上该处有问题
          if (semctl(semid, 1, SETVAL, 1) < 0)
          {
            fatal ("semctl");
          }

          return (semid);
}
//回收共享两个内存区和一个信号量集合
void myremove()
{
      if (shmctl(shmid1, IPC_RMID, NULL) < 0)
      {
        fatal("shmctl");
      }
      if (shmctl(shmid2, IPC_RMID, NULL) < 0)
      {
        fatal("shmctl");
      }
      if (semctl(semid, 0, IPC_RMID, NULL) < 0)
         fatal("semctl");
       
      exit(0);
}

void reader(int semid, struct databuf *buf1, struct databuf *buf2)
{
      for(;;)
      {
       unsigned short val= semctl(semid,0,GETVAL,null);
       if(val<=0)
       {
         semop(semid,&v1,1);
       }
       else{
         //申请第一个信号灯资源
         semop(semid, &p1, 1)
       }
       //从键盘读入数据,放在buf1->d_buf,
       //read第一个参数是文件描述符,其中0表示从终端输入:如键盘
       buf1->d_nread = read(0, buf1->d_buf, SIZ);
       //v操作,释放第一个信号灯资源   
       semop(semid, &v1, 1);
      
       //p操作,申请第二个信号灯资源,若没有资源,则阻塞进程直到有资源.
       semop(semid, &p2, 1);
     
       buf2->d_nread = read(0, buf2->d_buf, SIZ);
      //v操作,释放第二个信号灯资源
       semop(semid, &v2, 1);
     }
            
}

void writer(int semid, struct databuf *buf1, struct databuf *buf2)
{
      for(;;)
      {
        //p操作,等待第一个信号的资源    
        semop(semid, &p1, 1);
        //1代表输出到屏幕
        write(1, buf1->d_buf, buf1->d_nread);
        //释放第一个信号灯资源
        semop(semid, &v1, 1);
     
        //p操作,申请第二个信号灯资源,若没有资源,则阻塞进程直到有资源.
        semop(semid, &p2, 1);
      
        write(1, buf2->d_buf, buf2->d_nread);
 
        semop(semid, &v2, 1);
                                                          }
}

int main()
{
      int semid, pid;
       
      struct databuf *buf1, *buf2;
     
      semid = getsem();
      getshm (&buf1, &buf2);

      switch(pid=fork())
      {
        case -1:
            fatal("fork");
            break;
        case 0:
            writer(semid, buf1, buf2);
            break;
        default:
       
        //在主进程中把中断程序的ctrl+c和myremove函数建立联系,
        //来回收系统资源:共享内存区,信号量.
        signal (SIGINT, myremove);
        reader(semid, buf1, buf2);
        break;
     }
      exit(0);
}

 

分享到:
评论

相关推荐

    信号量对共享内存上锁示例代码

    通过这样的方式,信号量确保了在任何时刻只有一个进程能够访问共享内存,实现了互斥访问,从而避免了数据竞争的问题。这种机制在多进程或多线程环境中尤为重要,保证了系统的稳定性和数据的正确性。在实际开发中,...

    共享内存例子

    在这个"共享内存例子"中,我们将探讨如何创建和使用共享内存,以及如何通过多个独立的可执行文件(exe)进行通信。 首先,创建共享内存涉及以下步骤: 1. **指定内存大小**:你需要确定要共享的数据量,这将决定...

    一个VC写的内存共享的例子

    4. **同步操作**: 为了确保在多进程环境中安全地访问共享内存,通常需要配合使用信号量(Semaphore)、事件(Event)或互斥体(Mutex)。例如,当一个进程正在写入共享内存时,应锁定该区域,防止其他进程同时写入。...

    linux信号量的源码例子

    1. **创建信号量**:使用`sem_init()`函数创建一个内核级信号量。如果是在进程间共享,需要传递第三个参数为非零值。例如: ```c sem_t sem; sem_init(&sem, 1, 0); // 创建一个互斥量,初始值为0,可跨进程共享 ```...

    内存共享 例子

    DLLMemShare可能是一个包含内存共享功能的动态库文件,它的具体实现可能包括以下关键知识点: 1. **内存映射文件(Memory-Mapped File)**:这是一种将文件内容映射到进程地址空间的技术,使得多个进程可以共享同一...

    Qt进程间共享内存区例子

    标题为“Qt进程间共享内存区例子”,这个例子包括两个部分:`sharedmemory_write`(数据共享发起端)和`sharedmemory_read`(数据共享接收端)。 共享内存是一种高效的IPC机制,因为它允许多个进程直接读写同一块...

    Visual C++信号量线程同步的简单实例工程

    在Windows API中,我们可以使用CreateSemaphore函数创建一个信号量对象,并通过WaitForSingleObject或WaitForMultipleObjects函数来等待信号量。 接下来,我们探讨线程同步的基本概念。在多线程环境中,线程同步是...

    shm.rar_shm 数据_共享内存_进程共享内存

    标题中的“shm.rar_shm 数据_共享内存_进程共享内存”指的是一个关于Linux系统中使用共享内存(Shared Memory)进行进程间通信的示例或教程。在这个案例中,多个进程会周期性地将数据写入共享内存区域,而另一个进程...

    记录自己共享内存学习笔记

    互斥锁可以确保只有一个进程可以访问共享内存,而信号量可以控制进程对共享内存的访问顺序。 BlowSnow中的共享内存接口封装了共享内存的管理和操作,提供了一个易于使用的接口来创建和访问共享内存。HShareMemMgr类...

    信号量YUV.zip_信号量处理

    `shm_com.h`可能包含与共享内存相关的头文件,因为信号量常常与共享内存一起使用,用于控制多个进程对同一块内存的访问。 信号量分为两种类型:二进制信号量(Binary Semaphore)和计数信号量(Counting Semaphore...

    linux c下多进程的例子

    以下是一个简单的例子,演示了一个进程写入共享内存,另一个进程读取: ```c #include #include #include #include #include #include #include #define SHM_SIZE 256 int main() { int shmid; // 共享...

    Linux进程间通信-信号量通信进程互斥实例.pdf

    在这个例子中,`semget((key_t)1234, 1, 0666 | IPC_CREAT)` 创建了一个键值为1234的信号量集,其中1表示只包含一个信号量,0666是权限模式,`IPC_CREAT`表示如果信号量集不存在则创建。 - `set_semvalue()`函数设置...

    使用信号量实现线程同步

    1. **创建信号量**:使用`CreateSemaphore()`函数创建一个信号量对象,指定初始计数值和最大值。初始计数值表示资源的初始可用数量,最大值限制了资源的最大可用数量。 2. **线程入口函数**:每个线程都有自己的...

    进程间通讯---共享内存的使用方法

    为了同步多个进程对共享内存的访问,还可以结合信号量或者互斥锁等同步机制。 总结起来,共享内存是一种强大的进程间通信机制,适用于需要高速数据交换的场景。在C语言中,利用POSIX API可以方便地创建、映射和管理...

    使用信号量进行多任务同步

    在这个例子中,`TaskA`和`TaskB`都可以尝试获取同一个信号量,但只有当信号量可用时,它们才能执行临界区内的代码。这样,即使两个任务并发运行,也能确保对共享资源的访问有序,避免了竞态条件。 通过信号量,UCOS...

    电子-深入理解和实现RTOS连载9信号量应用演示.pdf

    信号量是一个计数器,用于多线程环境下的同步控制访问共享资源。在给定文件中,我们看到的是关于RTOS中信号量应用的演示。在深入讲解之前,先简要回顾下RTOS以及信号量的基本概念。 RTOS是一种设计用于管理计算机...

    内存共享示例(C#)

    在C#编程语言中,我们可以使用多种技术来实现内存共享,这些技术包括但不限于:内存映射文件、共享内存、委托事件、线程间通信以及通过网络套接字等。下面将详细阐述这些方法,并结合"Client"、"MQAD"和"Server"这三...

    信号量 linux嵌入式开发

    此时,信号量就能作为保护机制,确保在任何时候只有一个进程能够访问共享内存。 举个例子,假设我们有三个进程A、B和C,它们都需要访问一块共享内存。我们可以创建一个二进制信号量,初始值为1。当进程A访问共享...

    Linux 进程间通讯共享内存方式.docx

    `key`通常设置为`IPC_PRIVATE`,这会创建一个新的共享内存对象。`size`定义了共享内存的大小,单位为字节。`shmflg`参数可以包含`IPC_CREAT`,表示如果不存在相应的共享内存则创建,若同时包含`IPC_EXCL`,则只有当...

    单台服务器的php进程之间实现共享内存的方法_.docx

    10. **示例代码**: 例子展示了如何创建一个共享内存段,如何读写数据,并提供了使用`ipcs`和`ipcrm`命令的例子。 总结,通过本文介绍的方法,开发者可以有效地在单台服务器上的PHP进程中实现共享内存,从而提高程序...

Global site tag (gtag.js) - Google Analytics