- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在学习《Unix 环境中的高级编程》,第 15 章的练习 17 有问题。
练习要求读者“使用建议记录锁定在父项和子项之间交替”。
而且我发现如果不使用 usleep() 就无法完成。 没有什么可以阻止内核在解锁记录后继续调度父进程,反之亦然。
有人知道答案吗?提前致谢。
这是我的代码:
ex17.c
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/wait.h>
#include "ch14/lock.h"
#define NLOOPS 1000
#define SIZE sizeof(long) /* size of shared memory area */
static int update(long *ptr)
{
return (*ptr)++; /* return value before increment */
}
int main(int argc, char* argv[])
{
int fd, counter, lockFd;
pid_t pid;
void *area;
if((fd = open("/dev/zero", O_RDWR)) < 0)
{
perror("open error");
exit(1);
}
if((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
{
perror("mmap error");
exit(1);
}
close(fd); /*can close /dev/zero now that it's mapped */
if((lockFd = open("ex17.lock", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
{
perror("open error");
exit(-1);
}
/* insure parent runs first */
writew_lock(lockFd, 0, SEEK_SET, 1); /* first byte in the lock file represent parent */
writew_lock(lockFd, 1, SEEK_SET, 1); /* second byte in the lock file represent child */
if((pid = fork()) < 0)
{
perror("fork error");
exit(1);
}else if(pid > 0){ /* parent */
for(int i = 0; i<NLOOPS; i+=2)
{
writew_lock(lockFd, 0, SEEK_SET, 1);
readw_lock(lockFd, 1, SEEK_SET, 1);
if((counter = update((long*)area)) != i)
{
fprintf(stderr, "parent: expected %d, got %d\n", i, counter);
exit(1);
}else{
printf("%s got %d\n", "parent", counter);
}
un_lock(lockFd, 1, SEEK_SET, 1);
usleep(1000); /*if without this line, there is nothing to stop kernel continually scheduling parent.*/
readw_lock(lockFd, 0, SEEK_SET, 1);
}
waitpid(pid, NULL, 0);
} else {
for(int i=1; i<NLOOPS+1; i+=2)
{
writew_lock(lockFd, 1, SEEK_SET, 1);
readw_lock(lockFd, 0, SEEK_SET, 1);
if((counter = update((long*)area)) != i)
{
fprintf(stderr, "child: expected %d, got %d\n", i, counter);
exit(1);
}else{
printf("%s got %d\n", "child", counter);
}
un_lock(lockFd, 0, SEEK_SET, 1);
usleep(1000);
readw_lock(lockFd, 1, SEEK_SET, 1);
}
}
exit(0);
}
ch14/lock.h
#ifndef CH14_LOCK_H_INCLUDED
#define CH14_LOCK_H_INCLUDED
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int lock_reg(int, int, int, off_t, int, off_t);
pid_t lock_test(int, int, off_t, int, off_t);
#define read_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
#define is_read_lockable(fd, offset, whence, len) (lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
#define is_write_lockable(fd, offset, whence, len) (lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)
#endif // CH14_LOCK_H_INCLUDED
ch14/lock.c
#include "lock.h"
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
lock.l_whence = whence; /* byte offset, relative to l_whence */
lock.l_start = offset; /* byte offset, relative to l_whence */
lock.l_len = len; /* #bytes (0 means to EOF) */
return fcntl(fd, cmd, &lock);
}
pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type; /* F_RDLCK OR F_WRLCK */
lock.l_start = offset; /* byte offset, relative to l_whence */
lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
lock.l_len = len; /* #bytes (0 means to EOF) */
if(fcntl(fd, F_GETLK, &lock) < 0)
{
perror("fcntl error");
exit(-1);
}
if(lock.l_type == F_UNLCK)
{
return 0; /* false, region isn't locked by another proc */
}else{
return lock.l_pid; /* true, return pid of lock owner */
}
}
最佳答案
建议锁实现因类 unix 操作系统而异,但它们通常 are not mandatory by default ,Linux 就是这种情况。 man fcntl
包含咨询锁和强制锁的部分;从后者开始(这里的“以上”是指前者):
The above record locks may be either advisory or mandatory, and are advisory by default. Advisory locks are not enforced and are useful only between cooperating processes.
这意味着为了使锁有效,每个协作进程都必须检查它是否可以在获取锁之前获取一个锁。 man fcntl
为 F_GETLK
调用说了一些关于此的事情:
F_GETLK (struct flock *)
On input to this call, lock describes a lock we would like to place on the file. If the lock could be placed, fcntl() does not actually place it, but returns F_UNLCK in the l_type field of lock and leaves the other fields of the structure unchanged. If one or more incompatible locks would prevent this lock being placed, then fcntl() returns details about one of these locks in the l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the PID of the process holding that lock.
因此您使用 F_GETLK 提交的结构可能更改了一些字段以指示结果——这是您需要检查的内容。如果成功,您可以调用 F_SETLK 来实际应用锁。1如果不成功,您需要等到它成功,并且这些调用都不是阻塞,意思是无论情况如何,他们都会立即返回。这就是需要短暂 sleep 的地方,因为如果您只是一遍又一遍地循环检查锁,您将忙于循环一个处理器(使其无所事事地最大化)。然而,如果你加入 5 或 10 毫秒的被动延迟,循环将大部分被动地不做任何事情(即,没有最大化处理器)。这种延迟应该只发生在检查失败之后;如果检查成功,立即设置锁。
所有这些都可以放在一个函数中。它并不关心让进程稳定交替,但这实际上是一种人为的标准:如果你想在“现实生活”中实现那个目标,你就不会这样做。但是,这并非不可能。我要尝试的第一件事是在函数开始时使用比循环中长几倍的 sleep ,这样释放锁然后再次获取它的进程将延迟比一个同时试图在检查/设置循环中获取它的进程。
1。不幸的是,这意味着一个潜在的竞争条件,一个进程可能会在另一个进程的检查和设置调用之间设置一个锁——这个系统的一个弱点。
关于我们可以使用不带 usleep() 的咨询记录锁定在父子之间交替吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24850183/
我想交织相同模式和相等长度的两个向量。说: a <- rpois(lambda=3,n=5e5) b <- rpois(lambda=4,n=5e5) 我想交织或交织这两个向量,以创建一个等效于c(a
我有两个矩阵,我想以交替方式交织/交错/堆叠在彼此之上/rbind。 ranks=1:3 names=c("Karl", "Klaus", "Mary") x <- cbind(ranks, name
我在 JavaScript 中有一个字符串,如下所示: "This {{@is}} a $|test$| string with $|@string$| delimiters {{as}} follo
那么,我正在尝试“合并”一个字符串 (a) 和一个字符串列表 (b): a = '1234' b = ['+', '-', ''] 获得所需的输出(c): c = '1+2-34' 所需输出字符串中的
我有几个可变长度的数组,其中填充了表示好数据 block 和坏数据 block 的元组。 input = [ [(True, 0, 400), (False, 400, 500), (True
我有一个包含 3 个单元格的表,我想知道是否可以在每个单元格之间“旋转”数据? 基本上,在设定的时间后,我希望第一个单元格中的数据移动到第二个单元格,第二个单元格数据移动到第三个单元格,第三个单元格数
使用 RichFaces dataTable 组件交替行颜色的最简单方法是什么? 最佳答案 查找组件的 rowClasses 属性。 抱歉.. 阅读 richfaces 文档两秒钟后就明白了。 :)
我想创建一个有 4 列的表格,但只显示 3 列。所以我理想情况下有一个跨越 3 列的 div 并应用溢出:隐藏。单击按钮时,我希望第 3 列(公司 2)向左滑动,并替换为第 4 列(公司 3),以便将
有没有办法在 AngularJS 中替代 ng-repeats ? 例如,假设我有两个数组。 数组1 [a1, a2, a3, ...] 数组2 [b1, b2, b3, ...] 我想针对中型和大屏
我有三个包含元素的列表: a = [[0,1],[2,3],...] b = [[5,6],[7,8],...] c = [] 我想将 a 和 b 中的元素 append 到 c 中以获得: c =
我喜欢在 MATLAB 中绘制经过傅立叶变换的信号。通过 set(gca,'xtick',peaks,'FontSize',12);我可以在 x 轴上显示峰值。但有时,峰值靠得太近,显示峰值的文本与其
我正在使用 CSS Grid 为我的网站构建服务列表。整个网站网格中的一行被分成两个 CSS 网格列。 在第一行的第一列中,有一项服务的描述。在第二列中,有一个代表服务的图像。 每一行,描述和图像交替
我有以下 html 代码: 1 2 3 4 5 6 7 8 我想做的是使用奇数/偶数 nth-child 选择器对它们进行一些交替
在下面的代码示例中,我将 window.status 从“a”替换为“b” function alternateViaIntrvl() { setInterval('alterStatus()
下面的CSS和HTML代码生成 News Interviews ---------------------- Djing Break dance ---------------------- 为什么横
我曾经在 tableView willDisplay cell 方法中使用这段代码,但它没有准确地交替颜色 - 它几乎做到了,但有时仍然搞砸了 1 或 2 个相同的颜色和我不确定。 我发现一些建议在我
我的问题的本质是解决方案太多,我想在围绕它构建基础设施之前找出哪一个在优缺点中胜出。 (为了本论坛的目的进行了简化)这是一个拍卖网站,其中五个拍卖按排名#1-5 存储,#1 是当前特色拍卖。其他四个人
如果可能的话,我正在尝试找出是否有一种方法可以替换内容行分隔符的颜色。 例如: 问题是它必须是自动的,所以我假设可能需要 javascript,但我找不到这样的东西。我知道有些事情表明如果你有类似 t
这个看似简单的问题困扰了我整整 10 年。 (好的,不是每天!) 它在 IE 中运行良好,但在 FF 和 Chrome 中运行不正常,这通常表示代码有问题...我想在两侧都有 DIV 框(它们实际上是
我想找到交替 [0, 1, 0, 1] 所需的最少翻转次数,例如给定 [1, 1, 0, 1]。所以在这种情况下,它是一次翻转。 def solution(A): count = 0
我是一名优秀的程序员,十分优秀!