Usage of get_fs and set_fs

 最近在看 drbd的源代碼,內核模塊 socket通信中有下面一段程序:

  1.  mm_segment_t oldfs;
  2.     struct kvec iov = {
  3.         .iov_base = buf,
  4.         .iov_len = size,
  5.     };
  6.     struct msghdr msg = {
  7.         .msg_iovlen = 1,
  8.         .msg_iov = (struct iovec *)&iov,
  9.         .msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL)
  10.     };
  11.     int rv;
  12.     oldfs = get_fs();
  13.     set_fs(KERNEL_DS);
  14.     rv = sock_recvmsg(sock, &msg, size, msg.msg_flags);
  15.     set_fs(oldfs);

再看看內核中的定義:

  1. #define KERNEL_DS       MAKE_MM_SEG(0xFFFFFFFFUL)
  2. #define USER_DS         MAKE_MM_SEG(PAGE_OFFSET)
  3. #define get_ds()        (KERNEL_DS)
  4. #define get_fs()        (current_thread_info()->addr_limit)
  5. #define set_fs(x)       (current_thread_info()->addr_limit = (x))

其作用是用來修改當前進程的內存訪問權限。

      When you make a system call from user space, the first thing that is checked is if the address of the parameter is well within the legal virtual address space (i.e. 0 to 3 GB for the user space). If this is not so, the call will fail. If you want to make the same system call from the Kernel Space( Virtual Address 3 - 4 GB) however, this address checking has to be avoided so that the call will not fail. Now, every process has a tak_struct associated with it and this structure contains the legal virtual address boundaries for that process( Virtual Address space represented by mm_segment_t). The get_fs() macro will retrieve this boundary and the set_fs() will set it with a value. So, when you want to access a memory region which is beyond the User Space Virtual Address limit( i.e. falling in the Kernel Space Virtual Address region)。
set KERNEL_DS when user space address is used

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章