posix和system v 信號量哪個更快?

posix命名信號量,書上說是將信息存入fifo文件中進行同步的,而system v信號量,是將信息存入內核。

按理來說,內核裡面的調用應該比fifo要快吧?

為什麼我用兩種信號量,對同一種簡單的生產者消費者模型做測試,釋放和阻塞10000次,posix反而更快呢?


1. 你看的哪本書?

2. 你在哪個系統下做的測試?代碼?

3. 為什麼要用信號量?


POSIX sem 實現是基於futex的。 在無競爭條件下,不需要陷入內核,執行系統調用,其實現是非常輕量級的。

System V sem 則不同,無論有無競爭都要執行系統調用,因此性能落了下風。

POSIX sem 由於沒有事事煩擾內核,所以內核也無法幫他記錄 sem_adj ,即POSIX sem 並沒有UNDO功能。


@-@

Linux裡面,寫有限緩衝區生產者與消費者,生產者訪問10000000*2,消費者訪問10000000*2,用POSIX實現共享內存互斥和用系統V實現進行比較,前者運行時間是後者的1/4。。。

我用系統V做還以為死循環了。。。被坑死啦QAQ


The Linux Programming Interface 53.5 Comparisons with Other Synchronization Techniques提到POSIX和SYSV兩種版本的semaphore,有競爭的時候POSIX版本會快一些

glibc的實現(nptl/sysdeps/unix/sysv/linux/sem_{wait,post}.c nptl/sysdeps/unix/sysv/linux/sem_wait.c),semop是系統調用的wrapper;而無競爭的時候sem_{wait,post}只需要原子操作,沒有系統調用,因此可能會快些。

#define _DEFAULT_SOURCE 1
#include &
#include &
#include &


#include &
#include &
#include &
#include &
#define REP(i, n) FOR(i, 0, n)
#define FOR(i, a, b) for (int i = (a); i &< (b); i++) #define N 10000000 sem_t *sem; int semid; struct sembuf sop1, sop2; void *posix1(void *arg) { REP(i,N) if (sem_wait(sem) &< 0) err(1, "sem_wait"); return NULL; } void *posix2(void *arg) { REP(i,N) if (sem_post(sem) &< 0) err(1, "sem_post"); return NULL; } void *sysv1(void *arg) { REP(i,N) if (semop(semid, sop1, 1) &< 0) err(1, "semop"); return NULL; } void *sysv2(void *arg) { REP(i,N) if (semop(semid, sop2, 1) &< 0) // may fail if the value exceeds semvmx err(1, "semop"); return NULL; } int main(int argc, char *argv[]) { pthread_t pid1, pid2; if (! argv[1]) { puts("posix"); if ((sem = sem_open("/meow", O_CREAT, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED) err(1, "sem_open"); if (pthread_create(pid1, NULL, posix1, NULL)) errx(1, "pthread_create"); if (pthread_create(pid2, NULL, posix2, NULL)) errx(1, "pthread_create"); } else { puts("sysv"); if ((semid = semget(IPC_PRIVATE, 1, IPC_CREAT | S_IRWXU)) &< 0) err(1, "semget"); sop1.sem_op = -1; sop1.sem_num = 0; sop1.sem_flg = 0; sop2.sem_op = 1; sop2.sem_num = 0; sop2.sem_flg = 0; if (pthread_create(pid1, NULL, sysv1, NULL)) errx(1, "pthread_create"); if (pthread_create(pid2, NULL, sysv2, NULL)) errx(1, "pthread_create"); } if (pthread_join(pid1, NULL) || pthread_join(pid2, NULL)) errx(1, "pthread_join"); if (! argv[1]) { if (sem_close(sem) &< 0) err(1, "sem_close"); } else { if (semctl(semid, 0, IPC_RMID) &< 0) err(1, "semctl"); } return 0; }


都很慢,多線程是個不好的設計,能不用盡量別用


推薦閱讀:

同為開源的類unix系統,為什麼FreeBSD遠沒有Linux流行?
除了Windows和UNIX內核兩大桌面操作系統外,歷史上是否曾出現其他具有一定實用價值的操作系統?
Linux 算不算是 UNIX 的一個分支?
Atom, Vim, Visual Studio Code, Emacs 哪個好?
C的結構體成員變數的命名有必要加前綴嗎?

TAG:Linux | C編程語言 | Unix | POSIX |