Trusty มี API สำหรับการพัฒนาแอปพลิเคชัน/บริการ 2 คลาส ได้แก่
- แอปพลิเคชันหรือบริการที่เชื่อถือได้ซึ่งทำงานบนโปรเซสเซอร์ TEE
- แอปพลิเคชันปกติ/ไม่น่าเชื่อถือซึ่งทำงานบนโปรเซสเซอร์หลักและใช้บริการที่มี โดยแอปพลิเคชันที่เชื่อถือได้
ทรัสตี API โดยทั่วไปแล้วจะอธิบายถึงระบบ Trusty Inter-Process Communication (IPC) ซึ่งรวมถึงการสื่อสารกับโลกที่ไม่ปลอดภัย ซอฟต์แวร์ที่ทำงานบน ผู้ประมวลผลข้อมูลหลักสามารถใช้ Trusty API เพื่อเชื่อมต่อกับแอปพลิเคชัน/บริการที่เชื่อถือได้ และแลกเปลี่ยนข้อความที่กำหนดเองกับพวกเขา เหมือนกับบริการเครือข่ายผ่าน IP ขึ้นอยู่กับแอปพลิเคชันที่จะตัดสินรูปแบบข้อมูลและความหมายของข้อมูลเหล่านี้ โดยใช้โปรโตคอลระดับแอป การส่งข้อความที่เชื่อถือได้ รับประกันโดยโครงสร้างพื้นฐานของ Trusty ที่สำคัญ (ในรูปแบบของไดรเวอร์ ที่ทำงานบนโปรเซสเซอร์หลัก) และการสื่อสารจะไม่พร้อมกันโดยสมบูรณ์
พอร์ตและช่องทาง
แอปพลิเคชัน Trusty ใช้พอร์ตเพื่อแสดงจุดสิ้นสุดของบริการในรูปแบบ
ของเส้นทางที่มีชื่อซึ่งไคลเอ็นต์เชื่อมต่อ ซึ่งจะให้แท็กที่เรียบง่ายตามสตริง
รหัสบริการของลูกค้าที่จะใช้ แบบแผนการตั้งชื่อเป็นรูปแบบ DNS ย้อนกลับ
การตั้งชื่อ เช่น com.google.servicename
เมื่อไคลเอ็นต์เชื่อมต่อกับพอร์ต ลูกค้าจะได้รับช่องทางสำหรับการโต้ตอบ กับบริการ บริการต้องยอมรับการเชื่อมต่อขาเข้าและเมื่อ วิดีโอก็ได้รับช่องเช่นกัน โดยพื้นฐานแล้ว ระบบจะใช้พอร์ตเพื่อค้นหาบริการ จากนั้นการสื่อสารจะเกิดขึ้นผ่านช่องทางที่เชื่อมต่อ 2 ช่องทาง (เช่น อินสแตนซ์การเชื่อมต่อบนพอร์ต) เมื่อลูกค้าเชื่อมต่อกับพอร์ต รูปแบบสมมาตร สร้างการเชื่อมต่อ 2 ทิศทางแล้ว ไคลเอ็นต์ที่ใช้เส้นทางแบบ 2 ด้านนี้อยู่ และเซิร์ฟเวอร์สามารถแลกเปลี่ยนข้อความตามต้องการจนกว่าฝ่ายใดฝ่ายหนึ่งจะตัดสินใจฉีก ลดการเชื่อมต่อ
สร้างได้เฉพาะแอปพลิเคชันที่เชื่อถือด้านความปลอดภัยหรือโมดูลเคอร์เนลของ Trusty เท่านั้น พอร์ต แอปพลิเคชันที่ทำงานในฝั่งที่ไม่ปลอดภัย (ในโลกปกติ) สามารถ เชื่อมต่อกับบริการที่เผยแพร่โดยด้านที่ปลอดภัยเท่านั้น
แอปพลิเคชันที่เชื่อถือได้สามารถเป็นได้ทั้งไคลเอ็นต์และ ทำงานพร้อมกันได้ แอปพลิเคชันที่เชื่อถือได้ซึ่งเผยแพร่บริการ (ในฐานะ เซิร์ฟเวอร์) อาจต้องเชื่อมต่อกับบริการอื่นๆ (ในฐานะไคลเอ็นต์)
API ของแฮนเดิล
แฮนเดิลคือจำนวนเต็มที่ไม่มีเครื่องหมายซึ่งแสดงถึงทรัพยากร เช่น พอร์ตและ ซึ่งคล้ายกับข้อบ่งชี้ไฟล์ใน UNIX หลังจากสร้างแฮนเดิลแล้ว จะวางลงในตารางแฮนเดิลเฉพาะแอปพลิเคชันและนำไปใช้อ้างอิงได้ ในภายหลัง
ผู้โทรสามารถเชื่อมโยงข้อมูลส่วนตัวกับแฮนเดิลได้โดยใช้
เมธอด set_cookie()
เมธอดใน Handle API
แฮนเดิลจะใช้ได้ในบริบทของแอปพลิเคชันเท่านั้น แอปพลิเคชันควร
ไม่ส่งผ่านค่าของแฮนเดิลไปยังแอปพลิเคชันอื่น เว้นแต่จะมีการระบุไว้อย่างชัดแจ้ง
ที่ระบุ ควรแปลค่าแฮนเดิลเท่านั้นด้วยการเปรียบเทียบกับค่าแฮนเดิล
INVALID_IPC_HANDLE #define,
ซึ่งแอปพลิเคชันสามารถใช้เป็น
แสดงว่าแฮนเดิลไม่ถูกต้องหรือไม่ได้ตั้งค่า
set_cookie()
เชื่อมโยงข้อมูลส่วนตัวที่ผู้โทรให้ไว้กับแฮนเดิลที่ระบุ
long set_cookie(uint32_t handle, void *cookie)
[in] handle
: แฮนเดิลใดก็ตามที่แสดงผลโดยการเรียก API รายการใดรายการหนึ่ง
[in] cookie
: ชี้ไปที่ข้อมูลพื้นที่ผู้ใช้ที่กำหนดเองในแอปพลิเคชัน Trusty
[retval]: NO_ERROR
เมื่อสำเร็จ, < 0
รหัสข้อผิดพลาด
การโทรนี้มีประโยชน์ในการจัดการเหตุการณ์เมื่อเหตุการณ์ดังกล่าวเกิดขึ้นในภายหลัง สร้างแฮนเดิลแล้ว กลไกการจัดการเหตุการณ์จะจัดเตรียมแฮนเดิล และคุกกี้ของตัวแฮนเดิลกลับไปยัง เครื่องจัดการเหตุการณ์
ใช้การเรียก wait()
เพื่อรอเหตุการณ์ต่างๆ ได้
รอ()
รอให้มีเหตุการณ์เกิดขึ้นในแฮนเดิลหนึ่งๆ ในระยะเวลาที่ระบุ
long wait(uint32_t handle_id, uevent_t *event, unsigned long timeout_msecs)
[in] handle_id
: แฮนเดิลใดก็ตามที่แสดงผลโดยการเรียก API รายการใดรายการหนึ่ง
[out] event
: ตัวชี้ไปยังโครงสร้างที่แสดง
เหตุการณ์ที่เกิดขึ้นในแฮนเดิลนี้
[in] timeout_msecs
: ค่าระยะหมดเวลาเป็นมิลลิวินาที CANNOT TRANSLATE
ค่า -1 คือระยะหมดเวลาอนันต์
[retval]: NO_ERROR
หากเหตุการณ์ที่ถูกต้องเกิดขึ้นภายใน
ช่วงเวลาการหมดเวลาที่ระบุ ERR_TIMED_OUT
หากผ่านระยะหมดเวลาที่ระบุไว้แล้ว แต่ไม่ใช่
เกิดเหตุการณ์ < 0
สำหรับข้อผิดพลาดอื่นๆ
เมื่อดำเนินการสำเร็จ (retval == NO_ERROR
) การเรียก wait()
ในโครงสร้าง uevent_t
ที่ระบุด้วยข้อมูลเกี่ยวกับ
เหตุการณ์ที่เกิดขึ้น
typedef struct uevent { uint32_t handle; /* handle this event is related to */ uint32_t event; /* combination of IPC_HANDLE_POLL_XXX flags */ void *cookie; /* cookie associated with this handle */ } uevent_t;
ฟิลด์ event
มีชุดค่าผสมของค่าต่อไปนี้
enum { IPC_HANDLE_POLL_NONE = 0x0, IPC_HANDLE_POLL_READY = 0x1, IPC_HANDLE_POLL_ERROR = 0x2, IPC_HANDLE_POLL_HUP = 0x4, IPC_HANDLE_POLL_MSG = 0x8, IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10, … more values[TBD] };
IPC_HANDLE_POLL_NONE
- ไม่มีกิจกรรมที่รอดำเนินการอยู่จริง
ผู้โทรควรรีสตาร์ทการรอ
IPC_HANDLE_POLL_ERROR
- เกิดข้อผิดพลาดภายในที่ไม่ระบุ
IPC_HANDLE_POLL_READY
- ขึ้นอยู่กับประเภทแฮนเดิล ดังนี้
- สำหรับพอร์ต ค่านี้จะบ่งบอกว่ามีการเชื่อมต่อที่รอดำเนินการ
- สำหรับแชแนล ค่านี้จะบ่งบอกว่าเป็นการเชื่อมต่อแบบไม่พร้อมกัน
(ดู
connect()
) สร้างแล้ว
เหตุการณ์ต่อไปนี้เกี่ยวข้องกับช่องเท่านั้น
IPC_HANDLE_POLL_HUP
- บ่งบอกว่ามีการปิดช่องโดยแอปเทียบเท่าIPC_HANDLE_POLL_MSG
- ระบุว่ามีข้อความที่รอดำเนินการสำหรับช่องนี้IPC_HANDLE_POLL_SEND_UNBLOCKED
- บ่งบอกว่า ผู้โทรที่บล็อกการส่งอาจพยายามส่ง อีกครั้ง (ดูรายละเอียดในคำอธิบายsend_msg()
)
ควรเตรียมเครื่องจัดการเหตุการณ์เพื่อจัดการกับชุดค่าผสมของค่าที่ระบุ เหตุการณ์ เนื่องจากอาจมีการตั้งค่าบิตพร้อมกันหลายบิต ตัวอย่างเช่น สำหรับ เป็นไปได้ว่าจะมีข้อความที่รอดำเนินการ และการเชื่อมต่อถูกปิดโดย ในระดับเดียวกัน
กิจกรรมส่วนใหญ่เป็นแบบติดหนึบ จะคงอยู่ตราบเท่าที่เป็นไปตามเงื่อนไข
ยังคงอยู่ (เช่น ได้รับข้อความที่รอดำเนินการทั้งหมด และมีการเชื่อมต่อที่รอดำเนินการ
คำขอจะได้รับการจัดการ) ยกเว้นในกรณีของ
เหตุการณ์ IPC_HANDLE_POLL_SEND_UNBLOCKED
ซึ่ง
จะได้รับอนุมัติเมื่อมีการอ่าน และแอปพลิเคชันมีโอกาสเพียงครั้งเดียวที่จะ
จัดการ
โดยสามารถทำลายแฮนเดิลได้โดยการเรียกใช้เมธอด close()
ปิด()
ทำลายทรัพยากรที่เชื่อมโยงกับแฮนเดิลที่ระบุ และนำออกจาก ตารางแฮนเดิล
long close(uint32_t handle_id);
[in] handle_id
: แฮนเดิลเพื่อทำลาย
[retval]: 0 หากสำเร็จ ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
API เซิร์ฟเวอร์
เซิร์ฟเวอร์จะเริ่มต้นด้วยการสร้างพอร์ตที่มีชื่ออย่างน้อย 1 รายการที่แสดง จุดสิ้นสุดของบริการ พอร์ตแต่ละพอร์ตจะแสดงด้วยแฮนเดิล
เมธอดใน Server API
Port_create()
สร้างพอร์ตบริการที่มีชื่อ
long port_create (const char *path, uint num_recv_bufs, size_t recv_buf_size, uint32_t flags)
[in] path
: ชื่อสตริงของพอร์ต (ตามที่อธิบายไว้ข้างต้น) ช่วงเวลานี้
ชื่อต้องไม่ซ้ำกันในระบบ ไม่ซ้ำ
[in] num_recv_bufs
: จำนวนบัฟเฟอร์สูงสุดที่ช่องใช้
พอร์ตนี้สามารถจัดสรรล่วงหน้าเพื่ออำนวยความสะดวกในการแลกเปลี่ยนข้อมูลกับไคลเอ็นต์ กำลังนับบัฟเฟอร์
แยกต่างหากสำหรับข้อมูลที่ไปในทั้ง 2 ทิศทาง ดังนั้นการระบุ 1 ที่นี่จะหมายถึง 1
มีการจัดสรรบัฟเฟอร์การส่งและการรับ 1 รายการไว้ล่วงหน้า โดยทั่วไป จำนวนบัฟเฟอร์
ขึ้นอยู่กับข้อตกลงด้านโปรโตคอลระดับที่สูงกว่าระหว่างลูกค้ากับ
เซิร์ฟเวอร์ ตัวเลขอาจมีแค่ 1 ก็ได้ ในกรณีที่เป็นโปรโตคอลแบบซิงโครนัสมาก
(ส่งข้อความ รับคำตอบก่อนที่จะส่งอีกรายการ) แต่ตัวเลขสามารถ
เพิ่มเติมหากลูกค้าคาดว่าจะส่งข้อความมากกว่า 1 ข้อความก่อนที่จะตอบกลับ
(เช่น ข้อความหนึ่งเป็นอารัมภบทและอีกข้อความเป็นคำสั่งจริง)
ชุดบัฟเฟอร์ที่จัดสรรเป็นหน่วยต่อช่อง ดังนั้นการเชื่อมต่อ 2 ช่อง (แชนเนล) จะแยกกัน
จะมีชุดบัฟเฟอร์แยกกัน
[in] recv_buf_size
: ขนาดสูงสุดของบัฟเฟอร์แต่ละรายการใน
เหนือชุดบัฟเฟอร์ ค่านี้คือ
ขึ้นอยู่กับโปรโตคอลและจำกัดขนาดสูงสุดของข้อความที่คุณแลกเปลี่ยนได้
กับแอปเทียบเท่า
[in] flags
: ชุดค่าผสมของ Flag ที่ระบุลักษณะการทำงานเพิ่มเติมของพอร์ต
ค่านี้ควรเป็นชุดค่าผสมของค่าต่อไปนี้
IPC_PORT_ALLOW_TA_CONNECT
- อนุญาตการเชื่อมต่อจากแอปที่ปลอดภัยอื่นๆ
IPC_PORT_ALLOW_NS_CONNECT
- อนุญาตการเชื่อมต่อจากโลกที่ไม่ปลอดภัย
[retval]: จัดการพอร์ตที่สร้างขึ้นหากไม่ใช่ด้านลบ หรือเกิดข้อผิดพลาดที่เฉพาะเจาะจง ลบ
จากนั้นเซิร์ฟเวอร์จะสำรวจรายการแฮนเดิลพอร์ตสำหรับการเชื่อมต่อขาเข้า
โดยใช้การโทร wait()
เมื่อได้รับการเชื่อมต่อ
ซึ่งระบุด้วยบิต IPC_HANDLE_POLL_READY
ที่ตั้งค่าไว้ใน
ฟิลด์ event
ของโครงสร้าง uevent_t
ค่า
เซิร์ฟเวอร์ควรเรียก accept()
เพื่อทำการเชื่อมต่อให้เสร็จสิ้นและสร้าง
ช่อง (นำเสนอโดย
แฮนเดิลอื่น) ที่จะดึงข้อมูลสำหรับข้อความขาเข้าได้
ยอมรับ()
ยอมรับการเชื่อมต่อที่เข้ามาใหม่และรับแฮนเดิลของช่อง
long accept(uint32_t handle_id, uuid_t *peer_uuid);
[in] handle_id
: แฮนเดิลที่แสดงถึงพอร์ตที่ไคลเอ็นต์เชื่อมต่อ
[out] peer_uuid
: ชี้ไปที่โครงสร้าง uuid_t
ที่จะ
กรอก UUID ของแอปพลิเคชันไคลเอ็นต์ที่เชื่อมต่อ ทั้งนี้
จะตั้งเป็น 0 ทั้งหมดหากการเชื่อมต่อมาจากโลกที่ไม่ปลอดภัย
[retval]: จัดการแชแนล (ถ้าไม่เป็นลบ) ซึ่งเซิร์ฟเวอร์สามารถ แลกเปลี่ยนข้อความกับไคลเอ็นต์ (หรือรหัสข้อผิดพลาด)
API ของไคลเอ็นต์
ส่วนนี้ประกอบด้วยเมธอดใน Client API
เมธอดใน Client API
เชื่อมต่อ()
เริ่มการเชื่อมต่อกับพอร์ตที่ระบุตามชื่อ
long connect(const char *path, uint flags);
[in] path
: ชื่อพอร์ตที่เผยแพร่โดยแอปพลิเคชันของ Trusty
[in] flags
: ระบุลักษณะการทำงานเพิ่มเติมที่ไม่บังคับ
[retval]: จัดการช่องที่สามารถแลกเปลี่ยนข้อความกับ เซิร์ฟเวอร์; หากเป็นลบ
หากไม่ได้ระบุ flags
(พารามิเตอร์ flags
มีค่าเป็น 0) การเรียกใช้ connect()
จะเริ่มต้นการเชื่อมต่อแบบซิงโครนัส
ไปยังพอร์ตที่ระบุทันที
แสดงข้อผิดพลาดหากไม่มีพอร์ต และสร้างการบล็อกจนกว่า
หรือเซิร์ฟเวอร์ยอมรับการเชื่อมต่อเป็นอย่างอื่น
ลักษณะการทำงานนี้เปลี่ยนแปลงได้โดยการระบุชุดค่าผสมของ 2 ค่า ที่อธิบายไว้ด้านล่าง
enum { IPC_CONNECT_WAIT_FOR_PORT = 0x1, IPC_CONNECT_ASYNC = 0x2, };
IPC_CONNECT_WAIT_FOR_PORT
- บังคับให้connect()
เพื่อรอหากไม่มีพอร์ตที่ระบุทันทีขณะดำเนินการ
แทนที่จะล้มเหลวทันที
IPC_CONNECT_ASYNC
- หากมีการตั้งค่าไว้ จะเป็นการเริ่มต้นการเชื่อมต่อแบบไม่พร้อมกัน CANNOT TRANSLATE
แอปพลิเคชันมีการโพลสำหรับ
แฮนเดิลที่แสดงผล (โดยการเรียกใช้ wait()
สำหรับ
เหตุการณ์การเชื่อมต่อเสร็จสมบูรณ์ซึ่งระบุโดย IPC_HANDLE_POLL_READY
บิตที่ตั้งค่าในช่องเหตุการณ์ของโครงสร้าง uevent_t
ก่อนเริ่มต้น
การทำงานตามปกติ
API การรับส่งข้อความ
การเรียก API การรับส่งข้อความ จะทำให้สามารถส่งและอ่านข้อความผ่าน การเชื่อมต่อ (ช่อง) ที่สร้างไว้ก่อนหน้านี้ การเรียก API การรับส่งข้อความ คือ เหมือนกันทั้งสำหรับเซิร์ฟเวอร์และไคลเอ็นต์
ลูกค้าได้รับแฮนเดิลช่องโดยการออก connect()
และเซิร์ฟเวอร์จะได้รับแฮนเดิลช่องจากการเรียก accept()
ที่อธิบายไว้ข้างต้น
โครงสร้างของข้อความความน่าเชื่อถือ
ดังที่แสดงในตัวอย่างต่อไปนี้ ข้อความที่แลกเปลี่ยนโดย Trusty API จะมีปริมาณน้อยที่สุด โดยปล่อยให้เซิร์ฟเวอร์และไคลเอ็นต์ตกลงกันในความหมายของ เนื้อหาจริง:
/* * IPC message */ typedef struct iovec { void *base; size_t len; } iovec_t; typedef struct ipc_msg { uint num_iov; /* number of iovs in this message */ iovec_t *iov; /* pointer to iov array */ uint num_handles; /* reserved, currently not supported */ handle_t *handles; /* reserved, currently not supported */ } ipc_msg_t;
ข้อความอาจประกอบด้วยบัฟเฟอร์ที่ไม่ต่อเนื่องกันอย่างน้อย 1 รายการซึ่งแสดงเป็น
อาร์เรย์ของ iovec_t
โครงสร้าง Trusty จัดเรียงแบบกระจาย
อ่านและเขียนไปยังบล็อกเหล่านี้
โดยใช้อาร์เรย์ iov
เนื้อหาของบัฟเฟอร์ที่อธิบายได้
ตามอาร์เรย์ iov
จะกำหนดเองทั้งหมด
เมธอดใน Messaging API
send_msg()
ส่งข้อความผ่านช่องทางที่ระบุ
long send_msg(uint32_t handle, ipc_msg_t *msg);
[in] handle
: จัดการช่องที่ต้องการส่งข้อความ
[in] msg
: ชี้ไปที่ ipc_msg_t structure
ที่อธิบายข้อความ
[retval]: จำนวนไบต์ทั้งหมดที่ส่งเมื่อสำเร็จ ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
หากลูกค้า (หรือเซิร์ฟเวอร์) พยายามส่งข้อความผ่านช่องทางและ
ไม่มีพื้นที่ว่างในคิวข้อความของเพียร์ปลายทาง ช่องอาจ
ป้อนสถานะการส่งถูกบล็อก (ซึ่งไม่ควรเกิดขึ้นสำหรับฟังก์ชันซิงโครนัสแบบง่าย
โปรโตคอลคำขอ/การตอบกลับ แต่อาจเกิดขึ้นในกรณีที่ซับซ้อนกว่านั้น) นั่นคือ
ระบุโดยการส่งคืนรหัสข้อผิดพลาด ERR_NOT_ENOUGH_BUFFER
ในกรณีนี้ ผู้โทรจะต้องรอจนกว่าเพื่อนจะปล่อยว่าง
ที่ว่างในคิวการรับ โดยเรียกคืนการจัดการและเลิกใช้ข้อความ
ระบุด้วยการตั้งค่าบิต IPC_HANDLE_POLL_SEND_UNBLOCKED
ใน
ฟิลด์ event
ของโครงสร้าง uevent_t
แสดงผลโดยการเรียก wait()
get_msg()
รับข้อมูลเมตาเกี่ยวกับข้อความถัดไปในคิวข้อความขาเข้า
ของแชแนลที่ระบุ
long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);
[in] handle
: แฮนเดิลของช่องที่ต้องเรียกข้อมูลข้อความใหม่
[out] msg_info
: โครงสร้างข้อมูลของข้อความมีคำอธิบายดังต่อไปนี้
typedef struct ipc_msg_info { size_t len; /* total message length */ uint32_t id; /* message id */ } ipc_msg_info_t;
ระบบจะกำหนดรหัสที่ไม่ซ้ำกันให้กับแต่ละข้อความในชุดข้อความที่คงค้าง และกรอกความยาวรวมของแต่ละข้อความ หากกำหนดค่าและได้รับอนุญาตจาก อาจมีข้อความที่รอดำเนินการ (เปิด) หลายข้อความพร้อมกันสำหรับ ช่องทางที่เจาะจง
[retval]: ประสบความสำเร็จ NO_ERROR
ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
Read_msg()
อ่านเนื้อหาของข้อความที่มีรหัสที่ระบุ โดยเริ่มจาก ที่ระบุ
long read_msg(uint32_t handle, uint32_t msg_id, uint32_t offset, ipc_msg_t *msg);
[in] handle
: แฮนเดิลของช่องที่จะอ่านข้อความ
[in] msg_id
: รหัสของข้อความที่จะอ่าน
[in] offset
: ออฟเซ็ตลงในข้อความที่จะเริ่มอ่าน
[out] msg
: ชี้ไปที่โครงสร้าง ipc_msg_t
ที่อธิบาย
ชุดบัฟเฟอร์สำหรับจัดเก็บข้อความขาเข้า
ข้อมูล
[retval]: จำนวนไบต์ทั้งหมดที่จัดเก็บในบัฟเฟอร์ msg
บน
สำเร็จ ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
สามารถเรียกเมธอด read_msg
ได้หลายครั้ง โดยเริ่มต้นตั้งแต่
แตกต่าง (ไม่จำเป็นว่า
ตามลำดับ) ตามความจำเป็น
Put_msg()
เลิกใช้ข้อความที่มีรหัสที่ระบุ
long put_msg(uint32_t handle, uint32_t msg_id);
[in] handle
: แฮนเดิลของช่องที่ได้รับข้อความ
[in] msg_id
: รหัสข้อความที่เลิกใช้
[retval]: ประสบความสำเร็จ NO_ERROR
ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
ไม่สามารถเข้าถึงเนื้อหาข้อความได้อีกหลังจากเลิกใช้ข้อความไปแล้ว และ พื้นที่อื่นที่มีอยู่ถูกปล่อยว่างแล้ว
API ข้อบ่งชี้ไฟล์
File Descriptor API ประกอบด้วย read()
, write()
,
และ ioctl()
สาย การเรียกทั้งหมดนี้สามารถทำงานในชุดไฟล์ที่กำหนดไว้ล่วงหน้า (แบบคงที่) ได้
แต่เดิมเรียกด้วยเลขน้อยๆ ในปัจจุบัน
การใช้งาน พื้นที่ข้อบ่งชี้ไฟล์จะแยกจากแฮนเดิล IPC
พื้นที่ทำงาน File Descriptor API ใน Trusty คือ
คล้ายกับ API ที่ใช้ข้อบ่งชี้ไฟล์แบบดั้งเดิม
โดยค่าเริ่มต้น จะมีข้อบ่งชี้ไฟล์ที่กำหนดไว้ล่วงหน้า 3 แบบ (แบบมาตรฐานและที่รู้จัก) ดังนี้
- 0 - อินพุตมาตรฐาน การใช้งานเริ่มต้นของอินพุตมาตรฐาน
fd
ไม่จำเป็นต้องดำเนินการใดๆ (เนื่องจากแอปพลิเคชันที่เชื่อถือได้ไม่ได้ต้องการ คอนโซล) ดังนั้นการอ่าน การเขียน หรือการเรียกใช้ioctl()
ในfd
0 ควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
- 1 - เอาต์พุตมาตรฐาน สามารถกำหนดเส้นทางข้อมูลที่เขียนไปยังเอาต์พุตมาตรฐานได้ (ขึ้นอยู่กับ
ที่ระดับแก้ไขข้อบกพร่อง LK) เป็น UART และ/หรือบันทึกหน่วยความจำที่มีอยู่ในตัวเลือกที่ไม่ปลอดภัย
ขึ้นอยู่กับแพลตฟอร์มและการกำหนดค่า บันทึกการแก้ไขข้อบกพร่องที่ไม่สำคัญและ
ข้อความควรอยู่ในเอาต์พุตมาตรฐาน
read()
และioctl()
ไม่มีการดำเนินการ และควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
- 2 - ข้อผิดพลาดมาตรฐาน ข้อมูลที่เขียนถึงข้อผิดพลาดมาตรฐานควรกำหนดเส้นทางไปยัง UART
หรือบันทึกหน่วยความจำที่ใช้ได้ในด้านที่ไม่ปลอดภัย ทั้งนี้ขึ้นอยู่กับแพลตฟอร์มและ
การกำหนดค่า ขอแนะนำให้เขียนเฉพาะข้อความสำคัญตามมาตรฐาน
เนื่องจากสตรีมนี้มีแนวโน้มที่จะไม่มีการควบคุม
read()
และ เมธอดioctl()
ไม่ทำงานและควรแสดงข้อผิดพลาดERR_NOT_SUPPORTED
แม้ว่าคุณสามารถขยายข้อบ่งชี้ไฟล์ชุดนี้เพื่อนำไปใช้เพิ่มเติม
fds
(เพื่อใช้ส่วนขยายเฉพาะแพลตฟอร์ม) ขยายความต้องการด้านข้อบ่งชี้ไฟล์
คุณต้องใช้ความระมัดระวัง การขยายข้อบ่งชี้ไฟล์มีแนวโน้มที่จะสร้าง
ทับซ้อนกันและโดยทั่วไปจะไม่แนะนำ
เมธอดใน File Descriptor API
อ่าน()
พยายามอ่านข้อมูลสูงสุด count
ไบต์จากข้อบ่งชี้ไฟล์ที่ระบุ
long read(uint32_t fd, void *buf, uint32_t count);
[in] fd
: ตัวบ่งชี้ไฟล์ที่จะอ่าน
[out] buf
: ชี้ไปที่บัฟเฟอร์ที่ใช้จัดเก็บข้อมูล
[in] count
: จำนวนไบต์สูงสุดที่อ่านได้
[retval]: แสดงผลจำนวนไบต์ที่อ่าน ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
เขียน()
เขียนข้อมูลสูงสุด count
ไบต์ไปยังข้อบ่งชี้ไฟล์ที่ระบุ
long write(uint32_t fd, void *buf, uint32_t count);
[in] fd
: ตัวบอกไฟล์ที่จะเขียน
[out] buf
: ชี้ไปที่ข้อมูลที่จะเขียน
[in] count
: จำนวนไบต์สูงสุดที่จะเขียน
[retval]: แสดงผลจำนวนไบต์ที่เขียนแล้ว ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
ioctl()
เรียกใช้คำสั่ง ioctl
ที่ระบุสำหรับข้อบ่งชี้ไฟล์ที่กำหนด
long ioctl(uint32_t fd, uint32_t cmd, void *args);
[in] fd
: ตัวบอกไฟล์ที่จะเรียกใช้ ioctl()
[in] cmd
: คำสั่ง ioctl
[in/out] args
: ชี้ไปที่อาร์กิวเมนต์ ioctl()
API เบ็ดเตล็ด
เมธอดใน Miscellancies API
gettime()
แสดงเวลาของระบบปัจจุบัน (เป็นนาโนวินาที)
long gettime(uint32_t clock_id, uint32_t flags, int64_t *time);
[ใน] clock_id
: ขึ้นอยู่กับแพลตฟอร์ม Pass 0 สำหรับค่าเริ่มต้น
[in] flags
: สงวนไว้ ควรเป็น 0
[out] time
: ชี้ไปที่ค่า int64_t
ซึ่งจะจัดเก็บเวลาปัจจุบัน
[retval]: ประสบความสำเร็จ NO_ERROR
ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
nanosleep()
ระงับการดำเนินการแอปพลิเคชันการโทรตามระยะเวลาที่ระบุ และกลับมาใช้งานอีกครั้งหลังจากช่วงเวลาดังกล่าว
long nanosleep(uint32_t clock_id, uint32_t flags, uint64_t sleep_time)
[in] clock_id
: สงวนไว้ ควรเป็น 0
[in] flags
: สงวนไว้ ควรเป็น 0
[in] sleep_time
: เวลานอนหลับในหน่วยนาโนวินาที
[retval]: ประสบความสำเร็จ NO_ERROR
ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น
ตัวอย่างของแอปพลิเคชันเซิร์ฟเวอร์ที่เชื่อถือได้
แอปพลิเคชันตัวอย่างต่อไปนี้แสดงการใช้งาน API ข้างต้น ตัวอย่าง ทำให้เกิด "เสียงสะท้อน" บริการที่รองรับการเชื่อมต่อขาเข้าหลายรายการ แสดงกลับไปยังผู้โทร ข้อความทั้งหมดที่ได้รับจากไคลเอ็นต์นั้น จากด้านที่ปลอดภัยหรือไม่ปลอดภัย
#include <uapi/err.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <trusty_ipc.h> #define LOG_TAG "echo_srv" #define TLOGE(fmt, ...) \ fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__, ##__VA_ARGS__) # define MAX_ECHO_MSG_SIZE 64 static const char * srv_name = "com.android.echo.srv.echo"; static uint8_t msg_buf[MAX_ECHO_MSG_SIZE]; /* * Message handler */ static int handle_msg(handle_t chan) { int rc; struct iovec iov; ipc_msg_t msg; ipc_msg_info_t msg_inf; iov.iov_base = msg_buf; iov.iov_len = sizeof(msg_buf); msg.num_iov = 1; msg.iov = &iov; msg.num_handles = 0; msg.handles = NULL; /* get message info */ rc = get_msg(chan, &msg_inf); if (rc == ERR_NO_MSG) return NO_ERROR; /* no new messages */ if (rc != NO_ERROR) { TLOGE("failed (%d) to get_msg for chan (%d)\n", rc, chan); return rc; } /* read msg content */ rc = read_msg(chan, msg_inf.id, 0, &msg); if (rc < 0) { TLOGE("failed (%d) to read_msg for chan (%d)\n", rc, chan); return rc; } /* update number of bytes received */ iov.iov_len = (size_t) rc; /* send message back to the caller */ rc = send_msg(chan, &msg); if (rc < 0) { TLOGE("failed (%d) to send_msg for chan (%d)\n", rc, chan); return rc; } /* retire message */ rc = put_msg(chan, msg_inf.id); if (rc != NO_ERROR) { TLOGE("failed (%d) to put_msg for chan (%d)\n", rc, chan); return rc; } return NO_ERROR; } /* * Channel event handler */ static void handle_channel_event(const uevent_t * ev) { int rc; if (ev->event & IPC_HANDLE_POLL_MSG) { rc = handle_msg(ev->handle); if (rc != NO_ERROR) { /* report an error and close channel */ TLOGE("failed (%d) to handle event on channel %d\n", rc, ev->handle); close(ev->handle); } return; } if (ev->event & IPC_HANDLE_POLL_HUP) { /* closed by peer. */ close(ev->handle); return; } } /* * Port event handler */ static void handle_port_event(const uevent_t * ev) { uuid_t peer_uuid; if ((ev->event & IPC_HANDLE_POLL_ERROR) || (ev->event & IPC_HANDLE_POLL_HUP) || (ev->event & IPC_HANDLE_POLL_MSG) || (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) { /* should never happen with port handles */ TLOGE("error event (0x%x) for port (%d)\n", ev->event, ev->handle); abort(); } if (ev->event & IPC_HANDLE_POLL_READY) { /* incoming connection: accept it */ int rc = accept(ev->handle, &peer_uuid); if (rc < 0) { TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle); return; } handle_t chan = rc; while (true){ struct uevent cev; rc = wait(chan, &cev, INFINITE_TIME); if (rc < 0) { TLOGE("wait returned (%d)\n", rc); abort(); } handle_channel_event(&cev); if (cev.event & IPC_HANDLE_POLL_HUP) { return; } } } } /* * Main application entry point */ int main(void) { int rc; handle_t port; /* Initialize service */ rc = port_create(srv_name, 1, MAX_ECHO_MSG_SIZE, IPC_PORT_ALLOW_NS_CONNECT | IPC_PORT_ALLOW_TA_CONNECT); if (rc < 0) { TLOGE("Failed (%d) to create port %s\n", rc, srv_name); abort(); } port = (handle_t) rc; /* enter main event loop */ while (true) { uevent_t ev; ev.handle = INVALID_IPC_HANDLE; ev.event = 0; ev.cookie = NULL; /* wait forever */ rc = wait(port, &ev, INFINITE_TIME); if (rc == NO_ERROR) { /* got an event */ handle_port_event(&ev); } else { TLOGE("wait returned (%d)\n", rc); abort(); } } return 0; }
เมธอด run_end_to_end_msg_test()
จะส่งข้อความ 10,000 ข้อความแบบไม่พร้อมกัน
"เสียงก้อง" บริการและแฮนเดิล
คำตอบ
static int run_echo_test(void) { int rc; handle_t chan; uevent_t uevt; uint8_t tx_buf[64]; uint8_t rx_buf[64]; ipc_msg_info_t inf; ipc_msg_t tx_msg; iovec_t tx_iov; ipc_msg_t rx_msg; iovec_t rx_iov; /* prepare tx message buffer */ tx_iov.base = tx_buf; tx_iov.len = sizeof(tx_buf); tx_msg.num_iov = 1; tx_msg.iov = &tx_iov; tx_msg.num_handles = 0; tx_msg.handles = NULL; memset (tx_buf, 0x55, sizeof(tx_buf)); /* prepare rx message buffer */ rx_iov.base = rx_buf; rx_iov.len = sizeof(rx_buf); rx_msg.num_iov = 1; rx_msg.iov = &rx_iov; rx_msg.num_handles = 0; rx_msg.handles = NULL; /* open connection to echo service */ rc = sync_connect(srv_name, 1000); if(rc < 0) return rc; /* got channel */ chan = (handle_t)rc; /* send/receive 10000 messages asynchronously. */ uint tx_cnt = 10000; uint rx_cnt = 10000; while (tx_cnt || rx_cnt) { /* send messages until all buffers are full */ while (tx_cnt) { rc = send_msg(chan, &tx_msg); if (rc == ERR_NOT_ENOUGH_BUFFER) break; /* no more space */ if (rc != 64) { if (rc > 0) { /* incomplete send */ rc = ERR_NOT_VALID; } goto abort_test; } tx_cnt--; } /* wait for reply msg or room */ rc = wait(chan, &uevt, 1000); if (rc != NO_ERROR) goto abort_test; /* drain all messages */ while (rx_cnt) { /* get a reply */ rc = get_msg(chan, &inf); if (rc == ERR_NO_MSG) break; /* no more messages */ if (rc != NO_ERROR) goto abort_test; /* read reply data */ rc = read_msg(chan, inf.id, 0, &rx_msg); if (rc != 64) { /* unexpected reply length */ rc = ERR_NOT_VALID; goto abort_test; } /* discard reply */ rc = put_msg(chan, inf.id); if (rc != NO_ERROR) goto abort_test; rx_cnt--; } } abort_test: close(chan); return rc; }
API และแอปพลิเคชันสากลที่ไม่ปลอดภัย
ชุดของบริการ Trusty ซึ่งเผยแพร่จากด้านที่ปลอดภัยและ
เคอร์เนลเข้าถึงแอตทริบิวต์ IPC_PORT_ALLOW_NS_CONNECT
ได้
และโปรแกรมพื้นที่ผู้ใช้ที่ทำงานใน
ที่ไม่ปลอดภัย
สภาพแวดล้อมการดำเนินการในฝั่งที่ไม่ปลอดภัย (เคอร์เนลและพื้นที่ของผู้ใช้) แตกต่างจากสภาพแวดล้อมการดำเนินการในด้านที่ปลอดภัยอย่างเห็นได้ชัด ดังนั้นแทนที่จะมีไลบรารีเดียวสำหรับ 2 สภาพแวดล้อม API ชุดต่างๆ ในเคอร์เนล Client API จะจัดเตรียมโดย ไดรเวอร์เคอร์เนล Trusty-ipc และลงทะเบียนโหนดอุปกรณ์แบบตัวละครที่สามารถใช้ได้ เพื่อสื่อสารกับบริการที่ทำงานใน
พื้นที่ผู้ใช้ Trusty IPC Client API
ไลบรารี Trusty IPC Client API สำหรับพื้นที่ของผู้ใช้เป็นเลเยอร์สั้นๆ ที่ด้านบนของแท็ก
โหนดของอุปกรณ์ fd
โปรแกรมพื้นที่ทำงานของผู้ใช้เริ่มเซสชันการสื่อสาร
โดยโทรหา tipc_connect()
กำลังเริ่มต้นการเชื่อมต่อกับบริการ Trusty ที่ระบุ เป็นการภายใน
การเรียกใช้ tipc_connect()
จะเปิดโหนดอุปกรณ์ที่ระบุเพื่อ
รับข้อบ่งชี้ไฟล์และเรียกใช้ TIPC_IOC_CONNECT ioctl()
ด้วยพารามิเตอร์ argp
ซึ่งชี้ไปยังสตริงที่มี
ชื่อบริการที่จะเชื่อมต่อ
#define TIPC_IOC_MAGIC 'r' #define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char *)
ตัวบอกไฟล์ที่ได้จะใช้เพื่อสื่อสารกับบริการเท่านั้น
ที่ใช้สร้างเทมเพลตนี้ขึ้นมา คุณควรปิดข้อบ่งชี้ไฟล์โดย
กำลังโทรหา tipc_close()
เมื่อไม่จำเป็นต้องเชื่อมต่ออินเทอร์เน็ตอีกต่อไป
ข้อบ่งชี้ไฟล์ที่ได้รับจากการเรียก tipc_connect()
ทำงานเหมือนโหนดอุปกรณ์ที่เป็นตัวละครทั่วไป ข้อบ่งชี้ไฟล์มีดังนี้
- สามารถเปลี่ยนเป็นโหมดแบบไม่บล็อกได้หากต้องการ
- สามารถเขียนโดยใช้
write()
มาตรฐาน โทรเพื่อส่งข้อความไปยังอีกฝ่าย - สร้างแบบสำรวจได้ (โดยใช้การโทร
poll()
ครั้งหรือการโทรselect()
ครั้ง) สำหรับความพร้อมใช้งานของข้อความขาเข้าเป็นข้อบ่งชี้ไฟล์ทั่วไป - สามารถอ่านเพื่อเรียกข้อความขาเข้าได้
ผู้โทรส่งข้อความไปยังบริการ Trusty โดยเรียกใช้การเขียนสำหรับ
fd
ที่ระบุ ข้อมูลทั้งหมดที่ส่งผ่านไปยังการโทร write()
ข้างต้น
จะเปลี่ยนเป็นข้อความโดยไดรเวอร์ Trusty-ipc ข้อความคือ
ที่ส่งไปยังด้านที่ปลอดภัยซึ่งข้อมูลได้รับการจัดการโดยระบบย่อย IPC ใน
เคอร์เนล Trusty และไปยังปลายทางที่เหมาะสมและส่งไปยังแอป
การวนเหตุการณ์เป็นเหตุการณ์ IPC_HANDLE_POLL_MSG
ในช่องทางหนึ่งๆ
แฮนเดิล ซึ่งขึ้นอยู่กับ
โปรโตคอลเฉพาะบริการ บริการ Trusty อาจส่งการตอบกลับอย่างน้อย 1 รายการ
ข้อความที่ส่งไปยังฝั่งที่ไม่ปลอดภัย และวางไว้ใน
คิวข้อความข้อบ่งชี้ไฟล์ช่องที่เหมาะสมที่ผู้ใช้จะใช้เรียก
แอปพลิเคชันพื้นที่ทำงาน read()
สาย
Tipc_connect()
เปิดโหนดอุปกรณ์ tipc
ที่ระบุและเริ่ม
การเชื่อมต่อกับบริการ Trusty ที่ระบุ
int tipc_connect(const char *dev_name, const char *srv_name);
[in] dev_name
: เส้นทางไปยังโหนดอุปกรณ์ IPC ที่เชื่อถือได้เพื่อเปิด
[in] srv_name
: ชื่อบริการ Trusty ที่เผยแพร่แล้วที่จะเชื่อมต่อ
[retval]: ข้อบ่งชี้ไฟล์ถูกต้องเมื่อสำเร็จ มิฉะนั้น -1
Tipc_close()
ปิดการเชื่อมต่อกับบริการ Trusty ที่ระบุโดยข้อบ่งชี้ไฟล์
int tipc_close(int fd);
[in] fd
: ตัวอธิบายไฟล์ที่เคยเปิดโดย
การโทรจาก tipc_connect()
API ไคลเอ็นต์ IPC ของ Kernel Trusty
เคอร์เนล Trusty IPC Client API พร้อมใช้งานสำหรับไดรเวอร์เคอร์เนล ผู้ใช้ มีการใช้ Space Trusty IPC API เพิ่มเติมจาก API นี้
โดยทั่วไป การใช้งานทั่วไปของ API นี้จะประกอบไปด้วยโปรแกรมสร้าง
ออบเจ็กต์ struct tipc_chan
โดยใช้ tipc_create_channel()
แล้วใช้การเรียก tipc_chan_connect()
เพื่อเริ่มต้น
กับบริการ Trusty IPC ที่ทำงานบน
การเชื่อมต่อกับฝั่งรีโมตจะยกเลิกได้ด้วย
กำลังโทรหา tipc_chan_shutdown()
ตามด้วย
tipc_chan_destroy()
เพื่อล้างข้อมูลทรัพยากร
เมื่อได้รับการแจ้งเตือน (ผ่านการเรียกกลับของ handle_event()
)
ว่าสร้างการเชื่อมต่อสำเร็จแล้ว
ดังต่อไปนี้
- รับบัฟเฟอร์ข้อความโดยใช้การโทรของ
tipc_chan_get_txbuf_timeout()
- เขียนข้อความ และ
- จัดคิวข้อความโดยใช้
tipc_chan_queue_msg()
ในการจัดส่งไปยังบริการ Trusty (ในด้านที่ปลอดภัย) ซึ่ง เชื่อมต่อช่องแล้ว
หลังจากจัดคิวเรียบร้อยแล้ว ผู้โทรควรลืมบัฟเฟอร์ข้อความ
เนื่องจากบัฟเฟอร์ข้อความจะกลับไปที่บัฟเฟอร์พูลหลังจาก
การประมวลผลโดยรีโมต (เพื่อใช้ซ้ำในภายหลังสำหรับข้อความอื่นๆ) ผู้ใช้
จำเป็นต้องโทรหา tipc_chan_put_txbuf()
เท่านั้นหากติดต่อไม่ได้
อยู่ในคิวของบัฟเฟอร์ดังกล่าว หรือไม่จำเป็นต้องใช้อีกต่อไป
ผู้ใช้ API ได้รับข้อความจากฝ่ายระยะไกลโดยจัดการกับ
handle_msg()
Callback (ที่เป็นการโทร)
บริบทของคิวงาน Trusty-ipc rx
) ที่
แสดงตัวชี้ไปยังบัฟเฟอร์ rx
ที่มี
ข้อความขาเข้าที่ต้องจัดการ
คาดว่า Callback handle_msg()
จะส่งตัวชี้ไปยัง struct tipc_msg_buf
ที่ถูกต้อง
ซึ่งอาจเหมือนกับบัฟเฟอร์ข้อความขาเข้าหากมีการจัดการในเครื่อง
และไม่จำเป็นอีกต่อไป หรืออาจเป็นบัฟเฟอร์ใหม่ที่ได้จาก
สาย tipc_chan_get_rxbuf()
หากบัฟเฟอร์ขาเข้าอยู่ในคิว
เพื่อประมวลผลต่อไป ต้องติดตามบัฟเฟอร์ rx
ที่ถอดออก
และในที่สุดก็ปล่อยตัวโดยใช้การโทร tipc_chan_put_rxbuf()
เมื่อ
ก็ไม่จำเป็นอีกต่อไป
เมธอดใน Kernel Trusty IPC Client API
Tipc_create_channel()
สร้างและกำหนดค่าอินสแตนซ์ของแชแนล Trusty IPC สำหรับ อุปกรณ์ที่เชื่อถือได้-IPc
struct tipc_chan *tipc_create_channel(struct device *dev, const struct tipc_chan_ops *ops, void *cb_arg);
[in] dev
: ชี้ไปที่ Trusty-ipc ที่อุปกรณ์ใช้
สร้างช่องแล้ว
[in] ops
: ชี้ไปที่ struct tipc_chan_ops
มีความเฉพาะเจาะจงกับผู้โทร
Callback ที่ได้รับการเติมโฆษณา
[in] cb_arg
: ชี้ไปที่ข้อมูลที่จะส่งไป
ถึง tipc_chan_ops
Callback
[retval]: ชี้ไปยังอินสแตนซ์ที่สร้างขึ้นใหม่ของ
ประสบความสำเร็จ struct tipc_chan
อีก ERR_PTR(err)
โดยทั่วไป ผู้โทรต้องระบุ Callback 2 รายการซึ่งเรียกใช้แบบไม่พร้อมกัน เมื่อกิจกรรมที่เกี่ยวข้องเกิดขึ้น
มีการเรียกเหตุการณ์ void (*handle_event)(void *cb_arg, int event)
เพื่อแจ้งให้ผู้โทรทราบเกี่ยวกับการเปลี่ยนแปลงสถานะช่อง
[in] cb_arg
: ตัวชี้ข้อมูลที่ส่งไปยัง
การโทร tipc_create_channel()
ครั้ง
[in] event
: เหตุการณ์ที่อาจเป็นค่าใดค่าหนึ่งต่อไปนี้
TIPC_CHANNEL_CONNECTED
- หมายถึงการเชื่อมต่อที่สำเร็จ ไปยังรีโมตTIPC_CHANNEL_DISCONNECTED
- บ่งบอกว่าด้านระยะไกลปฏิเสธ คำขอเชื่อมต่อใหม่หรือได้รับคำขอ การยกเลิกการเชื่อมต่อสำหรับช่องที่เชื่อมต่อก่อนหน้านี้TIPC_CHANNEL_SHUTDOWN
- บ่งชี้ว่ารีโมตกำลังจะปิดเครื่อง ยุติการเชื่อมต่อทั้งหมดอย่างถาวร
struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb)
เรียกใช้ Callback เพื่อแจ้งเตือนว่าข้อความใหม่ถูก
ได้รับผ่านช่องทางที่ระบุ:
- [in]
cb_arg
: ตัวชี้ข้อมูลที่ส่งไปยัง การโทรtipc_create_channel()
ครั้ง - [in]
mb
: ชี้ไปที่struct tipc_msg_buf
กำลังอธิบายข้อความขาเข้า - [retval]: การใช้งาน Callback คาดว่าจะแสดงตัวชี้ไปยัง
struct tipc_msg_buf
ที่เป็นเคอร์เซอร์เดียวกันกับที่ได้รับได้ ในฐานะ พารามิเตอร์mb
หากข้อความได้รับการจัดการภายในเครื่องและไม่ได้ อีกต่อไป (หรือ เป็นบัฟเฟอร์ใหม่ที่ได้รับจากการเรียกtipc_chan_get_rxbuf()
)
Tipc_chan_connect()
เริ่มต้นการเชื่อมต่อกับบริการ Trusty IPC ที่ระบุ
int tipc_chan_connect(struct tipc_chan *chan, const char *port);
[in] chan
: ชี้ไปที่ช่องที่แสดงผลโดย
การโทร tipc_create_chan()
ครั้ง
[in] port
: ชี้ไปที่สตริงที่มีฟังก์ชัน
ชื่อบริการที่จะเชื่อมต่อ
[retval]: สำเร็จ 0 หรือมีข้อผิดพลาดทางลบ
ผู้โทรจะได้รับแจ้งเมื่อสร้างการเชื่อมต่อด้วยการรับ
การติดต่อกลับของ handle_event
Tipc_chan_shutdown()
สิ้นสุดการเชื่อมต่อกับบริการ Trusty IPC ที่เริ่มต้นไว้ก่อนหน้านี้
โดยการโทร tipc_chan_connect()
int tipc_chan_shutdown(struct tipc_chan *chan);
[in] chan
: ชี้ไปที่ช่องที่ส่งคืนโดย
การโทรจาก tipc_create_chan()
Tipc_chan_destroy()
ทำลายช่อง Trusty IPC ที่ระบุ
void tipc_chan_destroy(struct tipc_chan *chan);
[in] chan
: ชี้ไปที่ช่องที่แสดงผลโดย
การโทร tipc_create_chan()
ครั้ง
Tipc_chan_get_txbuf_timeout()
รับบัฟเฟอร์ข้อความที่ใช้เพื่อส่งข้อมูลผ่าน หากบัฟเฟอร์ไม่พร้อมใช้งานทันที ผู้โทรอาจถูกบล็อก สำหรับระยะหมดเวลาที่ระบุไว้ (เป็นมิลลิวินาที)
struct tipc_msg_buf * tipc_chan_get_txbuf_timeout(struct tipc_chan *chan, long timeout);
[in] chan
: ชี้ไปที่ช่องสำหรับจัดคิวข้อความ
[in] chan
: ระยะหมดเวลาสูงสุดที่รอจนถึง
บัฟเฟอร์ tx
พร้อมใช้งานแล้ว
[retval]: บัฟเฟอร์ข้อความที่ถูกต้องเมื่อทำสำเร็จ
ERR_PTR(err)
เมื่อเกิดข้อผิดพลาด
Tipc_chan_queue_msg()
จัดคิวข้อความที่จะส่งถึง ช่อง IPC ที่เชื่อถือได้
int tipc_chan_queue_msg(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ชี้ไปที่ช่องสำหรับจัดคิวข้อความ
[in] mb:
ชี้ไปที่ข้อความที่จะจัดคิว
(ได้รับจากการโทร tipc_chan_get_txbuf_timeout()
)
[retval]: สำเร็จ 0 หรือมีข้อผิดพลาดทางลบ
Tipc_chan_put_txbuf()
ปล่อยบัฟเฟอร์ข้อความ Tx
ที่ระบุ
ได้รับก่อนหน้านี้จากการเรียก tipc_chan_get_txbuf_timeout()
void tipc_chan_put_txbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ชี้ไปที่ช่อง
บัฟเฟอร์ข้อความนี้
[in] mb
: ชี้ไปที่บัฟเฟอร์ข้อความที่จะปล่อย
[retval]: ไม่มี
Tipc_chan_get_rxbuf()
รับบัฟเฟอร์ข้อความใหม่ที่ใช้รับข้อความผ่าน แชแนลที่ระบุ
struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);
[in] chan
: ชี้ไปที่ช่องที่มีบัฟเฟอร์ข้อความนี้
[retval]: บัฟเฟอร์ข้อความที่ถูกต้องเมื่อสำเร็จ, ERR_PTR(err)
เมื่อมีข้อผิดพลาด
Tipc_chan_put_rxbuf()
แสดงบัฟเฟอร์ข้อความที่ระบุซึ่งก่อนหน้านี้ได้มาจาก
tipc_chan_get_rxbuf()
สาย
void tipc_chan_put_rxbuf(struct tipc_chan *chan, struct tipc_msg_buf *mb);
[in] chan
: ชี้ไปที่ช่องที่มีบัฟเฟอร์ข้อความนี้
[in] mb
: ชี้ไปที่บัฟเฟอร์ข้อความที่จะปล่อย
[retval]: ไม่มี