2011-11-18 12 views
6
#include <stdio.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
#include <string> 
#include <vector> 
#include <iostream> 

using namespace std; 

struct LOCK { 
    string name; 
    string type; 
    vector <string> pids; 
}; 

int main() 

{ 

    int segment_id; 

    LOCK* shared_memory; 

    struct shmid_ds shmbuffer; 

    int segment_size; 

    const int shared_segment_size = 0x6400; 



    /* Allocate a shared memory segment. */ 

    segment_id = shmget (IPC_PRIVATE, shared_segment_size, 

        IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); 

    /* Attach the shared memory segment. */ 

    shared_memory = (LOCK*) shmat (segment_id, 0, 0); 

    printf ("shared memory attached at address %p\n", shared_memory); 

    /* Determine the segment's size. */ 

    shmctl (segment_id, IPC_STAT, &shmbuffer); 

    segment_size =    shmbuffer.shm_segsz; 

    printf ("segment size: %d\n", segment_size); 

    /* Write a string to the shared memory segment. */ 

    //sprintf (shared_memory, "Hello, world."); 
    shared_memory -> name = "task 1"; 
    shared_memory -> type = "read"; 
    (shared_memory -> pids).push_back("12345"); 
    (shared_memory -> pids).push_back("67890"); 

    /* Detach the shared memory segment. */ 

    shmdt (shared_memory); 



    /* Reattach the shared memory segment, at a different address. */ 

    shared_memory = (LOCK*) shmat (segment_id, (void*) 0x5000000, 0); 

    printf ("shared memory reattached at address %p\n", shared_memory); 

    /* Print out the string from shared memory. */ 

    //printf ("%s\n", shared_memory -> name); 
    cout << "Name of the shared memory: " + shared_memory -> name << endl; 

    /* Detach the shared memory segment. */ 

    shmdt (shared_memory); 



    /* Deallocate the shared memory segment. */ 

    shmctl (segment_id, IPC_RMID, 0); 



    return 0; 

} 

Tôi nhận được mã từ hướng dẫn về bộ nhớ dùng chung. Nó làm việc cho đến khi tôi định nghĩa struct LOCK và cố gắng viết LOCK thay vì char * vào bộ nhớ chia sẻ.Chương trình bộ nhớ chia sẻ C++ đơn giản được viết trên linux: lỗi phân đoạn

Ai đó có thể giúp tôi tìm ra vấn đề ở đây gây ra lỗi phân đoạn không?

+1

Tìm hiểu để biên dịch với tất cả các cảnh báo được kích hoạt và thông tin gỡ lỗi (ví dụ: 'g ++ Wall -g'). Sau đó, sử dụng trình gỡ lỗi 'gdb' của bạn để tìm ra lỗi SEGV ở đâu. –

+0

nếu sử dụng cấu trúc chuỗi và vectơ giống như trong bộ nhớ dùng chung là cần thiết, cách tốt nhất là sử dụng các mảng tĩnh trong cấu trúc LOCK. – totten

Trả lời

10

Bạn đang đặt vector s và string s vào bộ nhớ dùng chung. Cả hai lớp đó phân bổ bộ nhớ của riêng chúng, sẽ được cấp phát trong không gian địa chỉ của bất kỳ quá trình nào tạo ra phân bổ và sẽ tạo ra một segfault khi được truy cập từ quá trình khác. Bạn có thể thử chỉ định các trình phân bổ để sử dụng bộ nhớ chia sẻ đó, nhưng vì trong các trình phân bổ C++ 03 được giả sử là phi trạng thái, tôi không chắc liệu nó có khả thi hay không.

Cân nhắc xem cách Boost.Interprocess thực hiện điều đó.

+1

Ngay cả khi nó đã phân bổ trong bộ nhớ dùng chung, nó vẫn không hoạt động. Các lớp bên trong theo dõi các con trỏ tuyệt đối tới bộ nhớ mà chúng phân bổ. Nếu các phân đoạn bộ nhớ chia sẻ ánh xạ tại một địa chỉ khác, con trỏ sẽ không trỏ đến nơi chúng cần. Bạn cũng phải sử dụng con trỏ tương đối (liên quan đến cơ sở của phân đoạn bộ nhớ chia sẻ). –

+0

@DavidSchwartz, không phải là hệ điều hành ẩn mà từ các chương trình không gian người dùng? –

+2

@ TamásSzelei No. Làm sao có thể? Nếu bạn ánh xạ bộ nhớ chia sẻ tại địa chỉ X, thì con trỏ của bạn tới một đối tượng trong đó sẽ là X + A (trong đó A là độ lệch tương đối). Nếu một quá trình khác ánh xạ bộ nhớ chia sẻ tại địa chỉ Y (vì X được sử dụng trong quá trình đó hoặc chỉ bởi may mắn), nó cần một con trỏ tới Y + A để truy cập cùng một dữ liệu. Bạn không thể truyền con trỏ tuyệt đối (X + A) từ tiến trình này sang tiến trình khác hoặc đặt nó vào bộ nhớ dùng chung. Bạn phải truyền con trỏ tương đối (A) và mỗi tiến trình cần thêm địa chỉ ánh xạ cơ sở của nó vào con trỏ trước khi nó dereferences nó. –

1

Bạn có một số vấn đề. Điều hiển nhiên là bạn không được xây dựng đối tượng của mình. Ở dạng mờ đục, bạn đang thực hiện:

class Foo; 

Foo * p = get_memory(); 

p->bar = 5; // ouch! 

Những gì bạn cần phải làm, ít nhất:

void * addr = get_memory(sizeof(Foo)); 
Foo * p = ::new (addr) Foo; 
// do work 
p->~Foo(); // done 

(. Chỉ cần thay thế Foo bởi LOCK cho tình hình của bạn)

Tuy nhiên , nó trở nên phức tạp hơn: vectorstring yêu cầu phân bổ động. Bộ nhớ đó phải nằm trong cùng một không gian địa chỉ với số LOCK của bạn. Vì vậy, cách tiêu chuẩn để giải quyết này là viết cấp phát của riêng bạn và vượt qua rằng:

template <template <typename> class Alloc> 
struct Lock 
{ 
    typedef std::basic_string<char, std::char_traits<char>, Alloc<char>> shared_string; 

    shared_string name; 
    shared_string type; 

    std::vector<shared_string, Alloc<shared_string>> pids; 
}; 

Cuối cùng, bạn phải viết một lớp cấp phát phù hợp mà đặt bộ nhớ trong không gian địa chỉ giống như một trong đó đối tượng LOCK của bạn cuối cùng sẽ đi:

template <typename T> 
class shared_allocator { /* write this! */ } 

typedef Lock<shared_allocator> LOCK; 
+0

Vì nó đã được chỉ ra tại các ý kiến ​​trong câu trả lời của tôi, một cấp phát tùy chỉnh là không đủ. Các con trỏ tương đối là cần thiết để trỏ đến đúng vị trí trong mỗi không gian địa chỉ tiến trình. –

+0

@ K-ballo: Người cấp phát dự kiến ​​sẽ chăm sóc điều đó, phải không? Các trình phân bổ trạng thái mới sẽ làm cho cuộc sống dễ dàng hơn nhiều, vì bây giờ chúng có thể lưu trữ một địa chỉ cơ sở. –

+0

Không thực sự chắc chắn. Có lẽ nếu người cấp phát có một kiểu con trỏ không có con trỏ ... –

0

Tôi biết cách đây rất lâu. Nhưng tôi đã tìm kiếm làm thế nào để (nhớ) về chia sẻ mem và thread này là thú vị.

My Hai cent đến demander:

  • Hãy cân nhắc đọc đó và văn bản cho SharedMemory là giống hệt như đọc và viết thành một FileSystem.
  • ID bộ nhớ chia sẻ == tệp_handle từ mở (...);

    Vì vậy, ... Làm thế nào để bạn sắp xếp đúng cỡ và sau đó đọc-ghi std :: chuỗi hoặc thậm chí std :: vector vào một FILE? Bạn có thực sự 'mở rộng/thu nhỏ' một std :: string hoặc std :: vector từ bên trong một FILE ??

Cảm ơn bạn :)