操作系统实验——一些函数作用的总结

shm_open()

使用shm_open来操作共享内存
要点一定要用ftruncate把文件大小于设置为共享内存大小
shm_open () 创建并打开一个新的或打开一个现有的 POSIX 共享内存对象。POSIX 共享内存对象实际上是一个句柄,不相关的进程可以使用它来mmap()共享内存的同一区域。shm_unlink () 函数执行相反的 操作,删除之前由shm_open () 创建的对象。

#define SHARED_OBJ_NAME "/somename"

int shmFd = shm_open(SHARED_OBJ_NAME, O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(shmFd, sizeof(msg));  
...
operations
...

close(shmFd);


...

shm_unlink(SHARED_OBJ_NAME);
return 0;

mmap()

mmap() 系统调用能够将文件映射到内存空间,然后可以通过读写内存来读写文件。我们先来看看 mmap() 系统调用的用法吧,mmap() 函数的原型如下:
start:指定要映射的内存地址,一般设置为 NULL 让操作系统自动选择合适的内存地址。
length:映射地址空间的字节数,它从被映射文件开头 offset 个字节开始算起。
prot:指定共享内存的访问权限。可取如下几个值的可选:PROT_READ(可读), PROT_WRITE(可写), PROT_EXEC(可执行), PROT_NONE(不可访问)。
flags:由以下几个常值指定:MAP_SHARED(共享的) MAP_PRIVATE(私有的), MAP_FIXED(表示必须使用 start 参数作为开始地址,如果失败不进行修正),其中,MAP_SHARED , MAP_PRIVATE必选其一,而 MAP_FIXED 则不推荐使用。
fd:表示要映射的文件句柄。
offset:表示映射文件的偏移量,一般设置为 0 表示从文件头部开始映射。
函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

munmap()

int munmap(void *addr, size_t length);

取消内存映射,addr是由mmap成功返回的地址,length是要取消的内存长度,munmap 只是将映射的内存从进程的地址空间撤销,如果不调用这个函数,则在进程终止前,该片区域将得不到释放。

mkfifo()

int mkfifo(const char * pathname,mode_t mode);

mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此 umask值也会影响到FIFO文件的权限。Mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开 FIFO文件时,O_NONBLOCK旗标会有影响
1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。
2、没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。

返回值

若成功则返回0,否则返回-1,错误原因存于errno中。

错误代码

EACCESS 参数pathname所指定的目录路径无可执行的权限
EEXIST 参数pathname所指定的文件已存在。
ENAMETOOLONG 参数pathname的路径名称太长。
ENOENT 参数pathname包含的目录不存在
ENOSPC 文件系统的剩余空间不足
ENOTDIR 参数pathname路径中的目录存在但却非真正的目录。
EROFS 参数pathname指定的文件存在于只读文件系统内。

使用方法:

#define NAMED_PIPE "/var/lock/pipename"
...
{
  int ret = mkfifo(NAMED_PIPE, 0666);
  if (ret < 0)
      printf("Error when creating FIFO. %s\n", strerror(errno));
  message msg;
  int fd = open(NAMED_PIPE, O_WRONLY); //
  ret = write(fd, &msg, sizeof(msg));
  if (ret < 0)
      printf("Process %d: Error while writing message. %s\n", pid, strerror(errno));

  close(fd);
  unlink(NAMED_PIPE);
  return 0;
}

waitpid() & wait()

#include "csapp.h"

constexpr int N = 2;

signed main(void) {
    int status, i;
    pid_t pid[N], retpid;

    for (int i = 0;i < N;i++) {
        if ((pid[i] = fork()) == 0) exit(100 + i);
    }

    i = 0;
    while ((retpid = waitpid(pid[i++], &status, 0)) > 0) {
        if (WIFEXITED(status)) {
            printf("%d\n", status);
            printf("child %d terminated normally with exit status = %d\n",
                retpid, WEXITSTATUS(status));
        } else printf("child %d terminated abnormally\n", retpid);
    }

    // if (errno != ECHILD) unix_error("waitpid error");
    exit(0);
    return 0;
}

wait () 系统调用暂停当前进程的执行,直到其子进程之一终止。调用wait(&status)等价于:

waitpid(-1, &status, 0);

waitpid () 系统调用暂停当前进程的执行,直到由 pid 参数指定的子进程改变状态。默认情况下, waitpid () 仅等待终止的子进程,但此行为可通过 options参数进行修改,如下所述。

标签 描述
< -1 意思是等待任何进程组 ID 等于pid绝对值的子进程。
-1 意思是等待任何子进程。
0 意思是等待任何进程组ID等于调用进程的子进程。
> 0 意思是等待进程 ID 等于pid值的子进程。

原文地址:http://www.cnblogs.com/coldarra/p/16852675.html

发表评论

您的电子邮箱地址不会被公开。