![](/img/trans.png)
[英]C Linux pthreads: sending data from one thread to antoher using message queue gives unexpected result
[英]C Linux pthreads: sending data from one thread to another using shared memory gives unexpected result
我正在編寫一個程序,它將使用共享內存將50個整數從一個線程傳輸到另一個線程,並且在接收到整數后,接收方線程將打印它們。
代碼編譯時沒有任何錯誤或警告,但是當我運行它時,得到以下輸出:
pthread_create() for thread 1 returns: 0
pthread_create() for thread 2 returns: 0
Segmentation fault (core dumped)
到目前為止,這是我的代碼:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/msg.h>
#include <string.h>
//define declarations
#define SIZE 50
//function declarations
void *send_data();
void *receive_data();
int main()
{
pthread_t thread1;
pthread_t thread2;
int ret_val_t1;
int ret_val_t2;
//create thread1
ret_val_t1 = pthread_create( &thread1, NULL, send_data, NULL);
if(ret_val_t1)
{
fprintf(stderr,"Error - pthread_create() return value: %d\n",ret_val_t1);
exit(EXIT_FAILURE);
}
//create thread2
ret_val_t2 = pthread_create( &thread2, NULL, receive_data, NULL);
if(ret_val_t2)
{
fprintf(stderr,"Error - pthread_create() return value: %d\n",ret_val_t2);
exit(EXIT_FAILURE);
}
printf("pthread_create() for thread 1 returns: %d\n",ret_val_t1);
printf("pthread_create() for thread 2 returns: %d\n",ret_val_t2);
//wait untill threads are done with their routines before continuing with main thread
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *send_data(){
int shmid;
int *array;
int i = 0;
int SizeMem;
key_t key = 12345;
SizeMem = sizeof(*array)*SIZE;
shmid = shmget(key, SIZE*sizeof(int), IPC_CREAT);
array = (int *)shmat(shmid, 0, 0);
for(i=0; i<SIZE; i++)
{
array[i] = i;
}
for(i=0; i<SIZE; i++)
{
printf("\n%d---\n", array[i]);
}
printf("\nWritting to memory succesful--\n");
shmdt((void *) array);
}
void *receive_data(){
int shmid;
int *array;
int i = 0;
key_t key = 12345;
shmid = shmget(key, SIZE*sizeof(int), IPC_EXCL);
array = shmat(shmid, 0, SHM_RDONLY);
for(i=0; i<SIZE; i++)
{
printf("\n%d---\n", array[i]);
}
printf("\nRead to memory succesful--\n");
shmdt((void *) array);
}
在這種情況下,共享內存是一項昂貴的事務。 而且,您嘗試通過同一過程進行訪問,這沒有任何好處。
處理您的情況的更好方法是:
父進程的線程將有權訪問父進程堆內存。 這是使用簡單的概念。 為父進程創建一個堆對象,並在線程之間共享。
如許多評論中所述,共享內存是“進程間通信”通信概念之一,例如管道或命名管道或消息隊列等。
如果您用於練習,那就可以了。 但是,除了使用PROD之外,這是一項昂貴的事務。
如果您沒有對映射/共享的內存正確地應用鎖定和訪問限制,並且您沒有受到安全防火牆的保護,那么您就是在歡迎攻擊者。
一種競爭條件源於您的代碼。 您的第二個線程可以先獲取CPU,然后嘗試使用尚未創建的內存段。 由於它不存在,並且您不檢查錯誤,因此可以通過嘗試訪問NULL
地址的內存來獲取SIGSEGV
。
您必須放置禁止第二個線程進入共享內存訪問的同步設備,然后再創建它並填充數據。 就像是。
pthread_mutex_t lock;
pthread_cond_t shm_created_and_filled;
然后在main
初始化lock
和shm_created_and_filled
。
在寫入線程中,您將創建共享內存段並寫入數字,最后鎖定shm_created_and_filled
信號shm_created_and_filled
條件變量。 在閱讀線程中,您首先鎖定lock
變量,然后等待shm_created_and_filled
條件。 在讀取線程等待它之前,還有一個競爭條件,其中第一個線程運行並向shm_created_and_filled
條件發出信號(它將丟失該條件),但我將其作為練習留給了讀者。
使用ipcs
實用程序並查看ipcs -m
的輸出
根據shmget手冊頁 :
內容提要
#include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg);
...
除了上述標志之外,shmflg的最低有效9位還指定了授予所有者,組和其他人的權限 。 這些位與open(2)的mode參數具有相同的格式和相同的含義。 當前,系統未使用執行權限。
符合代碼
shmid = shmget(key, SIZE*sizeof(int), IPC_CREAT);
“ shmflg的最低有效9位”設置為零。
沒有人有權讀取/寫入您的共享內存段。
這樣會更好:
shmid = shmget(key, SIZE*sizeof(int), IPC_CREAT | 0600 );
這將為擁有用戶提供讀/寫權限。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.