我对Linux API sem_unlink()感到有些困惑,主要是在何时或为何调用它.我在Windows中使用了多年的信号量.在Windows中,一旦关闭了命名信号量的最后一个句柄,系统就会删除底层内核对象.但是在Linux中,开发人员需要通过调用sem_unlink()来删除内核对象.如果不这样做,内核对象将保留在/ dev/shm文件夹中.
我遇到的问题是,如果进程A调用sem_unlink()而进程B锁定了信号量,它会立即销毁信号量,当进程C出现时,进程B不再被信号量"保护".更重要的是,手册页充其量令人困惑:
"信号量名称立即被删除.一旦所有其他具有信号量打开的进程关闭它,信号量就会被破坏."
如果它必须等待其他进程关闭信号量,它如何立即销毁对象?
显然,我不明白在Linux上正确使用信号量对象.谢谢你的帮助.下面是我用来测试它的一些示例代码.
int main(void)
{
sem_t *pSemaphore = sem_open("/MyName", O_CREAT, S_IRUSR | S_IWUSR, 1);
if(pSemaphore != SEM_FAILED)
{
if(sem_wait(pSemaphore) == 0)
{
// Perform "protected" operations here
sem_post(pSemaphore);
}
sem_close(pSemaphore);
sem_unlink("/MyName");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 在我们的一个课程中,我们大量使用SemaphoreSlim.WaitAsync(CancellationToken)和取消它.
在调用WaitAsync之后不久取消挂起的调用时,我似乎遇到了问题SemaphoreSlim.Release()(很快,我的意思是在ThreadPool有机会处理排队的项目之前),它将信号量置于没有进一步锁定的状态被收购.
由于的是否非确定性性质ThreadPool项目的通话之间执行以Release()和Cancel(),下面的例子并不总是表现出的问题,这种情况下,我已经明确表示要忽略运行.
这是我试图证明问题的例子:
void Main()
{
for(var i = 0; i < 100000; ++i)
Task.Run(new Func<Task>(SemaphoreSlimWaitAsyncCancellationBug)).Wait();
}
private static async Task SemaphoreSlimWaitAsyncCancellationBug()
{
// Only allow one thread at a time
using (var semaphore = new SemaphoreSlim(1, 1))
{
// Block any waits
semaphore.Wait();
using(var cts1 = new CancellationTokenSource())
{
var wait2 = semaphore.WaitAsync(cts1.Token);
Debug.Assert(!wait2.IsCompleted, "Should be blocked by the existing wait");
// Release the …Run Code Online (Sandbox Code Playgroud) 我无法从javadocs中的信号量描述中理解以下内容.
请注意,调用acquire()时不会保持同步锁定,因为这会阻止项目返回到池中.信号量封装了限制访问池所需的同步,与维护池本身一致性所需的任何同步分开.
有人可以帮助我理解这个及其含义.
我有以下Java代码:
import java.util.concurrent.*;
class Foo{
static Semaphore s = new Semaphore(1);
public void fun(final char c, final int r){
new Thread(new Runnable(){
public void run(){
try{
s.acquire(r);
System.out.println(c+"_"+r);
s.release(r+1);
} catch(Exception e){ e.printStackTrace(); }
}
}).start();
}
}
class ths{
public static void main(String[]args) throws Exception{
Foo f = new Foo();
f.fun('B',2);
f.fun('F',6);
f.fun('A',1);
f.fun('C',3);
f.fun('D',4);
f.fun('E',5);
}
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,这应按顺序打印A_1到F_6并退出,但由于某种原因不会发生.它通常打印A_1和B_2然后卡住.
我的代码找不到任何明显的错误.有什么建议?
我需要创建两个子进程,每个子进程调用execvpater被分叉,可执行文件在它们之间共享POSIX信号量.
我是否需要创建共享内存或仅实现命名信号量?
我从以下链接得到两个答案:
但我对如何继续实施感到困惑.
我有一个简单的程序:
int main(void)
{
const char sname[]="xxx";
sem_t *pSemaphor;
if ((pSemaphor = sem_open(sname, O_CREAT, 0644, 0)) == SEM_FAILED) {
perror("semaphore initilization");
exit(1);
}
sem_unlink(sname);
sem_close(pSemaphor);
}
Run Code Online (Sandbox Code Playgroud)
当我在valgrind下运行它时,我收到以下错误:
==12702== Syscall param write(buf) points to uninitialised byte(s)
==12702== at 0x4E457A0: __write_nocancel (syscall-template.S:81)
==12702== by 0x4E446FC: sem_open (sem_open.c:245)
==12702== by 0x4007D0: main (test.cpp:15)
==12702== Address 0xfff00023c is on thread 1's stack
==12702== in frame #1, created by sem_open (sem_open.c:139)
Run Code Online (Sandbox Code Playgroud)
代码是从一个成功运行多年的大型项目中提取的,但现在却导致了分段错误.
我的示例中的valgrind错误与更大的项目中看到的相同,但它会导致崩溃,我的小例子没有.
我正在写一个模拟男女皆宜的浴室的程序(用于家庭作业).一次只允许4个人,如果其他性别已经在使用浴室,男女不能进入.我的问题是允许最多4人在浴室.从输出中可以看出,一次只有一个人进入洗手间.这是我的代码:
const int Delayx = 60;
int i;
int restroom = 0;
int Menwaiting = 0;
int Womenwaiting = 0;
semaphore max_capacity;
semaphore woman;
semaphore man;
semaphore mutex;
semaphore restroomcount;
void Delay(void)
{
int DelayTime;
DelayTime = random(Delayx);
for (i = 0; i<DelayTime; i++);
}
void Woman(void)
{
// for(;;){
Womenwaiting++;
//wait(mutex);
wait(woman);
wait(max_capacity);
//wait(woman);
wait(mutex);
wait(restroomcount);
cout << "A Woman has entered Restroom"<<endl;
cout << "People in the Restroom:" << restroom++ <<endl <<endl;
signal(restroomcount);
Womenwaiting--;
Delay();
wait(restroomcount);
cout << …Run Code Online (Sandbox Code Playgroud) 我正在研究一个在gentoo Linux上运行的非常大而复杂的PHP项目,这显然存在PHP信号量的一些问题.由于项目的规模和复杂性,我无法发布代码.我也无法提供再现问题的工作示例.它可能是由程序的复杂性以非威慑方式引起的.
问题出在这里:PHP代码正在尝试使用信号量写入和读取共享内存.在产生问题的情况下,执行以下操作:
在时间006.68,PHP 4.4.9执行以下代码,将5个字节的数据写入共享内存,$iVarKey其值为2010147023
sem_acquire($this->rSemaphore);
shm_put_var($this->rShm, $iVarKey, $mVar);
sem_release($this->rSemaphore);
Run Code Online (Sandbox Code Playgroud)
此操作在006.69时结束
在时间006.77,PHP 5.2.10执行以下代码,从共享内存中读取5个字节的数据,$iVarKey其值为622679600:
sem_acquire($this->rSemaphore);
$mVar = shm_get_var($this->rShm,$iVarKey);
sem_release($this->rSemaphore);
Run Code Online (Sandbox Code Playgroud)
此操作在006.78时结束
在时间016.01以下代码是由PHP 5.2.10(的代码相同的行中#2)执行,以从共享存储器读出5个字节的数据,以$iVarKey具有值2010147023(同#1):
sem_acquire($this->rSemaphore);
$mVar = shm_get_var($this->rShm,$iVarKey);
sem_release($this->rSemaphore);
Run Code Online (Sandbox Code Playgroud)
此操作现在大约需要2分钟,尽管具有相同的资源/信号量$iVarKey已提前约10秒发布.在此期间没有访问共享内存,因为我已经确定了每次调用sem_acquire!
如何sem_acquire阻止程序执行,尽管它不应该.也许这是版本4.4.9/5.2.10中的错误?有没有人看起来像类似的东西?有解决方法吗?我可以做些什么来进一步投资这个问题吗?
我真的很感激这个问题的帮助!
备注:
附加信息: - 我已经检查过每次通话sem_release,但似乎没有人回复FALSE.因此,我的问题并非来自失败的释放.- 当系统阻塞时,ipcs -s返回以下输出,与系统未阻塞时相同
------ Semaphore Arrays --------
key semid owner perms nsems
0x000f4240 0 root 666 3
0x00000001 32769 root 666 3
0x00000000 65538 apache 600 …Run Code Online (Sandbox Code Playgroud)