標籤:

uninx域基礎數據結構及操作

struct unix_proto_data unix_datas[NSOCKETS_UNIX]
#define last_unix_data (unix_datas + NSOCKETS_UNIX - 1) // 數組的最大邊界

unix_datas變數維護個數組,每個元素是unix_proto_data 結構。

struct unix_proto_data {
int refcnt; // 標記該結構是否已經被使用
struct socket *socket; // 該節點對應的socket
int protocol;
struct sockaddr_un sockaddr_un; // 協議簇和路徑名
short sockaddr_len; // sock_addr_un的長度
char *buf; // 讀寫緩衝區,實現全雙工
int bp_head, // 可寫空間的頭指針
int bp_tail; // 可寫空間的尾指針
struct inode *inode; // 路徑名對應的文件的inode
struct unix_proto_data *peerupd; // 對端的結構
struct wait_queue *wait; // 因為拿不到lock_flag被阻塞的隊列
int lock_flag; // 互斥訪問
};

分配一個unix_proto_data結構

// 分配一個沒有被使用的unix_proto_data結構
static struct unix_proto_data *
unix_data_alloc(void)
{
struct unix_proto_data *upd;

cli();
for(upd = unix_datas; upd <= last_unix_data; ++upd)
{ // 沒有被使用
if (!upd->refcnt)
{ // 初始化數據
upd->refcnt = -1; /* unix domain socket not yet initialised - bgm */
sti();
upd->socket = NULL;
upd->sockaddr_len = 0;
upd->sockaddr_un.sun_family = 0;
upd->buf = NULL;
upd->bp_head = upd->bp_tail = 0;
upd->inode = NULL;
upd->peerupd = NULL;
return(upd);
}
}
sti();
return(NULL);
}

查找

static struct unix_proto_data *
unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
struct inode *inode)
{
struct unix_proto_data *upd;

for(upd = unix_datas; upd <= last_unix_data; ++upd)
{
if (upd->refcnt > 0 && upd->socket &&
upd->socket->state == SS_UNCONNECTED &&
upd->sockaddr_un.sun_family == sockun->sun_family &&
upd->inode == inode)

return(upd);
}
return(NULL);
}

引用計數管理

static inline void unix_data_ref(struct unix_proto_data *upd)
{
if (!upd)
{
return;
}
++upd->refcnt;
}

static void unix_data_deref(struct unix_proto_data *upd)
{
if (!upd)
{
return;
}
//引用數為1說明沒人使用了,則釋放該結構對應的內存
if (upd->refcnt == 1)
{
if (upd->buf)
{
free_page((unsigned long)upd->buf);
upd->buf = NULL;
upd->bp_head = upd->bp_tail = 0;
}
}
--upd->refcnt;
}

推薦閱讀:

TAG:Linux | Linux內核 |