[討論] 想設計出一種一對多的Lock (inter-process)

看板C_and_CPP (C/C++)作者時間10年前 (2015/09/01 15:25), 10年前編輯推噓3(3017)
留言20則, 9人參與, 最新討論串1/1
Hi 我想要做一種client-server架構的Lock, 可以讓許多個client去wait 而server可以決定什麼時候該Lock (所有client在做Lock的時候會卡住) 什麼時候該Unlock (所有client在做Lock的時候會do nothing) 我的需求是這樣子的: 我有一個ringbuffer實作在shared memory裡 ringbuffer的每一塊資料都有一個編號, 這個編號只會逐漸增加 這塊sharememory的最前面會有一個表格, 記錄每個編號的data在ringbuffer的哪一個offset 新的資料會被插進來, 太久遠的資料會被丟棄 比如說目前的ringbuffer裡面資料是這樣分布的 1, 2, 3, 4, 5 這時候會有一個新的資料加進來, 他的編號會是6 而ringbuffer已經滿了, 所以1號會被丟棄 所以ringbuffer資料分佈會變成這樣 2, 3, 4, 5, 6 (先不管資料應該怎麼排列順序還有critical section的設計, 因為這不在討論之中) 回到我的問題: 當我的client已經把6號讀走了, 想要繼續讀7號(但是7號還沒被加進來) client就必須等待server把7號加進來 目前我的方法是client在for迴圈裡面做usleep(1000), 然後一直問7號來了沒 想也知道這樣很浪費系統資源 我打算這樣做: 設計一個semaphore, 平常的值為0 如果有一個client打算抓取還沒產生的data的時候(7號) 因為從表格中判斷出ringbuffer並不存在7號(也不知道甚麼時候會有) 所以client對這個semaphore減1 (然後程式卡住) 當server已經準備好7號data的時候, 就對這個semaphore加100(也許更多) 讓所有卡住的client都會瞬間解除blocking 當blocking解除之後server再把semaphore的值設為0 我的Linux還算很嫩, 目前想到的也就這招, 不知道大家還有什麼更好的辦法? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.32.91.30 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1441092306.A.101.html

09/01 16:13, , 1F
也許可以考慮改用 mutex 來實踐
09/01 16:13, 1F

09/01 16:14, , 2F
記得要處理好 deadlock 的問題就好了
09/01 16:14, 2F

09/01 16:32, , 3F
@Hazukashiine 您是指POSIX mutex? 這可以在interprocess
09/01 16:32, 3F

09/01 16:32, , 4F
使用嗎?
09/01 16:32, 4F

09/01 16:34, , 5F
你是說 IPC 嗎?我不確定,不過你可以先自己找一下
09/01 16:34, 5F

09/01 16:36, , 6F
09/01 16:36, 6F

09/01 18:54, , 7F
google一下pthread wait broadcast
09/01 18:54, 7F

09/01 19:53, , 8F
看起來 semaphore 就可以辦到了啊.
09/01 19:53, 8F

09/01 23:35, , 9F
reader writer lock?
09/01 23:35, 9F

09/02 19:16, , 10F
如果你一次只會加1個,我認為condition_variable就夠用
09/02 19:16, 10F

09/02 19:17, , 11F
不過你說一次會加多個,那應該要用semaphore
09/02 19:17, 11F

09/02 19:18, , 12F
readers writers的問題應該符合你的需求
09/02 19:18, 12F

09/02 19:30, , 13F
你想做的可能是disruptor pattern..請自查:)
09/02 19:30, 13F

09/03 03:30, , 14F
monitor ?
09/03 03:30, 14F
我利用semaphore做成這樣: semaphore剛建立出來的時候, 把semaphore的值設為0 (這樣任何想要-1的client都會被卡住) 在server端想要送一個signal給所有卡住的client時, 就這樣做 semctl(id, 0, SETVAL, 100); // 這會讓所有卡住的client unlock semctl(id, 0, SETVAL, 0); // 恢復為常態, 讓下次想要lock的client會立刻卡住 在client端就只是單純的-1而已 struct sembuf sb; sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = 0; semop(id, &sb, 1); ※ 編輯: jaw109 (114.32.91.30), 09/03/2015 12:41:06

09/03 16:28, , 15F
請試著考慮 sem_op = 0 可以怎麼使用.
09/03 16:28, 15F
感謝yvb的指點, 我改成這樣了 semaphore剛建立出來的時候, 把semaphore的值設為1 (這樣任何想要做sem_op = 0的client都會被卡住) 在server端想要送一個signal給所有卡住的client時, 就這樣做 semctl(id, 0, SETVAL, 0); // 這會讓所有卡住的client unlock semctl(id, 0, SETVAL, 1); // 恢復為常態, 讓下次想要做sem_op=0的client會立刻卡住 在client端就做sem_op=0 struct sembuf sb; sb.sem_num = 0; sb.sem_op = 0; sb.sem_flg = 0; semop(id, &sb, 1); [A ※ 編輯: jaw109 (114.32.91.30), 09/03/2015 18:11:55

09/06 22:01, , 16F
Reader Writer Lock 就可以了。Client acquire
09/06 22:01, 16F

09/06 22:02, , 17F
read lock, server acquire write lock
09/06 22:02, 17F

09/07 14:51, , 18F
我自己其實有實作read-write lock, 但改成文中的需求並不
09/07 14:51, 18F

09/07 14:51, , 19F
適合
09/07 14:51, 19F

09/08 23:25, , 20F
condition variable + wait_queue
09/08 23:25, 20F
文章代碼(AID): #1LvLBI41 (C_and_CPP)
文章代碼(AID): #1LvLBI41 (C_and_CPP)