2012-02-04 28 views
16

Tôi đã được giao nhiệm vụ trong một lớp để tạo thư viện chuỗi cấp người dùng trong C. Tôi đã tự hỏi liệu có ai có thể cho tôi một danh sách những thứ cần đọc để thực hiện điều này không. Tôi có một ý tưởng tốt là bắt đầu từ đâu, nhưng bất kỳ tài nguyên nào về chủ đề cấp người dùng và một số khía cạnh áp dụng của ngôn ngữ C có thể hữu ích sẽ cực kỳ có giá trị.Thực hiện Gói Chủ đề Cấp Người dùng

Tôi không rõ ràng về cách tôi sẽ triển khai trình lập lịch biểu cho việc này. Giả sử rằng tôi có một sự hiểu biết khá tốt về ngôn ngữ C và một số chức năng thư viện hữu ích hơn của nó.

+4

Bài tập có một chút khó khăn để thỏa mãn vì không thể thực hiện được "trong C". Bạn cần ít nhất một số lượng tối thiểu của assembly hoặc các phần mở rộng trình biên dịch tương đương để tạo thuận lợi cho việc tạo ra các bối cảnh thực thi mới và chuyển đổi giữa chúng. Hoặc bạn có thể viết máy ảo hoàn chỉnh của riêng mình và triển khai C để chạy trên máy ảo, nhưng tôi không nghĩ rằng đó là những gì người hướng dẫn của bạn có trong đầu ... –

+1

Đối với đa nhiệm hợp tác/luồng, bạn có thể tìm thấy getcontext/makecontext/chức năng setcontext hữu ích. – MetallicPriest

+0

Tôi không thể thấy làm thế nào điều này có thể được thực hiện mà không cần một số assembler để thực hiện việc tiết kiệm/khôi phục lại bối cảnh đăng ký và ngăn xếp con trỏ. Đó là mà không cần xem xét I/O và làm thế nào để chờ đợi nó. –

Trả lời

8

Tôi đã thực hiện việc này cho một bài tập về nhà mà không cần viết bất kỳ trình biên dịch nào cả. Cơ chế chuyển đổi luồng là setjmp/longjmp. Điều này liên quan đến việc phân bổ bộ nhớ cho ngăn xếp của mỗi luồng, sau đó rất cẩn thận xoa bóp các giá trị trong jmp_buff vì vậy việc thực hiện chuyển sang ngăn xếp của chuỗi tiếp theo.

Xem thêm của Russ Cox có thể đọc được libtask.

Chỉnh sửa để phản hồi nhận xét của OP: Khi quyết định thời điểm chuyển chủ đề có hai hướng chính: preemptive & hợp tác xã. Trong mô hình ưu tiên, bạn sẽ có thứ gì đó giống như tín hiệu hẹn giờ làm cho luồng thực thi chuyển sang luồng điều phối trung tâm, trong đó chọn luồng tiếp theo để chạy. Trong mô hình hợp tác, các chuỗi “thu được” với nhau, hoặc rõ ràng (ví dụ:, bằng cách gọi hàm yield() bạn sẽ cung cấp) hoặc ngầm (ví dụ:, yêu cầu khóa do một chuỗi khác giữ).

Hãy xem API của libtask để biết ví dụ về mô hình hợp tác, đặc biệt mô tả chức năng taskyield(). Đó là sản lượng rõ ràng mà tôi đã đề cập. Ngoài ra còn có các chức năng I/O không chặn trong đó bao gồm một năng suất tiềm ẩn - “nhiệm vụ” hiện tại được giữ cho đến khi I/O hoàn tất, nhưng các nhiệm vụ khác có cơ hội để chạy.

+0

Đây là cách tôi tưởng tượng rằng tôi sẽ chuyển đổi chuỗi. Tôi cho rằng kiến ​​thức trống lớn nhất của tôi là làm thế nào để xác định khi nào một chuỗi nên từ bỏ quyền kiểm soát để một chuỗi khác có thể chạy. tức là cách chủ đề xác định rằng họ có đủ thời gian. – SirensOfTitan

+0

@SirensOfTitan, tôi đã cập nhật câu trả lời của mình để đề cập đến những gì bạn vừa hỏi. –

4

Một lịch trình hợp tác đơn giản có thể được thực hiện trong C sử dụng swapcontext, hãy nhìn vào ví dụ trong swapcontext man page here, đây là sản lượng của nó:

$ ./a.out 
main: swapcontext(&uctx_main, &uctx_func2) 
func2: started 
func2: swapcontext(&uctx_func2, &uctx_func1) 
func1: started 
func1: swapcontext(&uctx_func1, &uctx_func2) 
func2: returning 
func1: returning 
main: exiting 

Như bạn có thể thấy nó là khá doable.

Lưu ý: nếu bạn hoán đổi ngữ cảnh bên trong bộ xử lý tín hiệu hẹn giờ, thì bạn có cho mình một bộ lập lịch trước, nhưng tôi không chắc liệu nó có an toàn hay không.

Edit: Tôi thấy điều này trong man page của sigaction đó cho thấy rằng nó có thể chuyển đổi bối cảnh bên trong một xử lý tín hiệu:

Nếu SA_SIGINFO được quy định tại sa_flags, sau đó sa_sigaction (thay vì sa_handler) chỉ định chức năng xử lý tín hiệu cho signum. Hàm này nhận số hiệu là đối số đầu tiên của nó, một con trỏ đến siginfo_t làm đối số thứ hai và một con trỏ tới số ucontext_t (bỏ trống *) làm đối số thứ ba.

+1

Cho rằng đây là một bài tập về nhà (và tôi đã gắn thẻ lại nó), OP nên kiểm tra xem điều đó có chấp nhận được hay không. Nhiều khả năng, người hướng dẫn đang tìm kiếm việc thực hiện chức năng 'swapcontext()' thay vì chỉ đơn giản là sử dụng nó. –

1

Bạn có thể tra cứu triển khai nguồn mở của Apple. Lưu ý rằng phần lớn nhất của mã thực sự là mã lắp ráp, bởi vì nó đòi hỏi một số thứ chuyên biệt mà bạn không thể làm trong C, giống như lấy địa chỉ trả về của khung ngăn xếp hoặc nhảy đến một địa chỉ tùy ý.

Chủ đề người dùng (thường được gọi là "sợi") thường sử dụng mô hình hợp tác; có nghĩa là, các luồng thực thi cho đến khi chúng quyết định chúng có đủ thời gian, sau đó sinh ra một luồng khác. Sử dụng hàng đợi ưu tiên, bạn có thể triển khai một trình lập lịch biểu thực hiện tác vụ đã chạy trong khoảng thời gian ngắn nhất. (Scheduler giữ một ca khúc của các nhiệm vụ đang chạy, và nhiệm vụ đang chạy quay trở lại khi nó quyết định nó có đủ. Bộ lập lịch cập nhật lượng thời gian tác vụ đã chạy, sau đó tạo ra thời gian thực hiện ít nhất.)

Các vấn đề liên quan