pipe.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2012-09-30 Bernard first version.
  9. * 2017-11-08 JasonJiaJie fix memory leak issue when close a pipe.
  10. * 2023-06-28 shell return POLLHUP when writer closed its channel on poll()
  11. * fix flag test on pipe_fops_open()
  12. * 2023-12-02 shell Make read pipe operation interruptable.
  13. */
  14. #include <rthw.h>
  15. #include <rtdevice.h>
  16. #include <stdint.h>
  17. #include <sys/errno.h>
  18. #include <ipc/condvar.h>
  19. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <poll.h>
  23. #include <sys/ioctl.h>
  24. #include <dfs_file.h>
  25. #include <resource_id.h>
  26. /* check RT_UNAMED_PIPE_NUMBER */
  27. #ifndef RT_UNAMED_PIPE_NUMBER
  28. #define RT_UNAMED_PIPE_NUMBER 64
  29. #endif
  30. #define BITS(x) _BITS(x)
  31. #define _BITS(x) (sizeof(#x) - 1)
  32. struct check_rt_unamed_pipe_number
  33. {
  34. /* -4 for "pipe" prefix */
  35. /* -1 for '\0' postfix */
  36. char _check[RT_NAME_MAX - 4 - 1 - BITS(RT_UNAMED_PIPE_NUMBER)];
  37. };
  38. /* check end */
  39. static void *resoure_id[RT_UNAMED_PIPE_NUMBER];
  40. static resource_id_t id_mgr = RESOURCE_ID_INIT(RT_UNAMED_PIPE_NUMBER, resoure_id);
  41. /**
  42. * @brief This function will open a pipe.
  43. *
  44. * @param fd is the file descriptor.
  45. *
  46. * @return Return the operation status.
  47. * When the return value is 0, it means the operation is successful.
  48. * When the return value is -1, it means the file descriptor is invalid.
  49. * When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
  50. */
  51. static int pipe_fops_open(struct dfs_file *fd)
  52. {
  53. int rc = 0;
  54. rt_pipe_t *pipe;
  55. pipe = (rt_pipe_t *)fd->vnode->data;
  56. if (!pipe)
  57. {
  58. return -1;
  59. }
  60. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  61. if ((fd->flags & O_ACCMODE) == O_RDONLY)
  62. {
  63. pipe->reader += 1;
  64. }
  65. if ((fd->flags & O_ACCMODE) == O_WRONLY)
  66. {
  67. pipe->writer += 1;
  68. }
  69. if (fd->vnode->ref_count == 1)
  70. {
  71. pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
  72. if (pipe->fifo == RT_NULL)
  73. {
  74. rc = -RT_ENOMEM;
  75. goto __exit;
  76. }
  77. }
  78. if ((fd->flags & O_ACCMODE) == O_RDONLY && !pipe->writer)
  79. {
  80. /* wait for partner */
  81. rc = rt_condvar_timedwait(&pipe->waitfor_parter, &pipe->lock,
  82. RT_INTERRUPTIBLE, RT_WAITING_FOREVER);
  83. if (rc != 0)
  84. {
  85. pipe->reader--;
  86. }
  87. }
  88. else if ((fd->flags & O_ACCMODE) == O_WRONLY)
  89. {
  90. rt_condvar_broadcast(&pipe->waitfor_parter);
  91. }
  92. __exit:
  93. rt_mutex_release(&pipe->lock);
  94. return rc;
  95. }
  96. /**
  97. * @brief This function will close a pipe.
  98. *
  99. * @param fd is the file descriptor.
  100. *
  101. * @return Return the operation status.
  102. * When the return value is 0, it means the operation is successful.
  103. * When the return value is -1, it means the file descriptor is invalid.
  104. */
  105. static int pipe_fops_close(struct dfs_file *fd)
  106. {
  107. rt_device_t device;
  108. rt_pipe_t *pipe;
  109. pipe = (rt_pipe_t *)fd->vnode->data;
  110. if (!pipe)
  111. {
  112. return -1;
  113. }
  114. device = &pipe->parent;
  115. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  116. if ((fd->flags & O_RDONLY) == O_RDONLY)
  117. {
  118. pipe->reader -= 1;
  119. }
  120. if ((fd->flags & O_WRONLY) == O_WRONLY)
  121. {
  122. pipe->writer -= 1;
  123. while (!rt_list_isempty(&pipe->reader_queue.waiting_list))
  124. {
  125. rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
  126. }
  127. }
  128. if (fd->vnode->ref_count == 1)
  129. {
  130. if (pipe->fifo != RT_NULL)
  131. {
  132. rt_ringbuffer_destroy(pipe->fifo);
  133. }
  134. pipe->fifo = RT_NULL;
  135. }
  136. rt_mutex_release(&pipe->lock);
  137. if (fd->vnode->ref_count == 1 && pipe->is_named == RT_FALSE)
  138. {
  139. /* delete the unamed pipe */
  140. rt_pipe_delete(device->parent.name);
  141. }
  142. return 0;
  143. }
  144. /**
  145. * @brief This function will get the pipe space size depends on the command.
  146. *
  147. * @param fd is the file descriptor.
  148. *
  149. * @param cmd is the command. It determines what data will get.
  150. *
  151. * FIONREAD The command to get the number of bytes in the pipe.
  152. *
  153. * FIONWRITE The command to get the number of bytes can be written to the pipe.
  154. *
  155. * @param args is the pointer to the data to store the read data.
  156. *
  157. * @return Return the operation status.
  158. * When the return value is 0, it means the operation is successful.
  159. * When the return value is -EINVAL, it means the command is invalid.
  160. */
  161. static int pipe_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
  162. {
  163. rt_pipe_t *pipe;
  164. int ret = 0;
  165. pipe = (rt_pipe_t *)fd->vnode->data;
  166. switch (cmd)
  167. {
  168. case FIONREAD:
  169. *((int*)args) = rt_ringbuffer_data_len(pipe->fifo);
  170. break;
  171. case FIONWRITE:
  172. *((int*)args) = rt_ringbuffer_space_len(pipe->fifo);
  173. break;
  174. default:
  175. ret = -EINVAL;
  176. break;
  177. }
  178. return ret;
  179. }
  180. /**
  181. * @brief This function will read data from pipe.
  182. *
  183. * @param fd is the file descriptor.
  184. *
  185. * @param buf is the buffer to store the read data.
  186. *
  187. * @param count is the length of data to be read.
  188. *
  189. * @return Return the length of data read.
  190. * When the return value is 0, it means O_NONBLOCK is enabled and there is no thread that has the pipe open for writing.
  191. * When the return value is -EAGAIN, it means there are no data to be read.
  192. */
  193. #ifdef RT_USING_DFS_V2
  194. static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
  195. #else
  196. static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
  197. #endif
  198. {
  199. int len = 0;
  200. rt_pipe_t *pipe;
  201. pipe = (rt_pipe_t *)fd->vnode->data;
  202. /* no process has the pipe open for writing, return end-of-file */
  203. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  204. while (1)
  205. {
  206. len = rt_ringbuffer_get(pipe->fifo, buf, count);
  207. if (len > 0 || pipe->writer == 0)
  208. {
  209. break;
  210. }
  211. else
  212. {
  213. if (fd->flags & O_NONBLOCK)
  214. {
  215. len = -EAGAIN;
  216. goto out;
  217. }
  218. rt_mutex_release(&pipe->lock);
  219. rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
  220. if (rt_wqueue_wait_interruptible(&pipe->reader_queue, 0, -1) == -RT_EINTR)
  221. return -EINTR;
  222. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  223. }
  224. }
  225. /* wakeup writer */
  226. rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
  227. out:
  228. rt_mutex_release(&pipe->lock);
  229. return len;
  230. }
  231. /**
  232. * @brief This function will write data to pipe.
  233. *
  234. * @param fd is the file descriptor.
  235. *
  236. * @param buf is a pointer to the data buffer to be written.
  237. *
  238. * @param count is the length of data to be write.
  239. *
  240. * @return Return the length of data written.
  241. * When the return value is -EAGAIN, it means O_NONBLOCK is enabled and there are no space to be written.
  242. * When the return value is -EPIPE, it means there is no thread that has the pipe open for reading.
  243. */
  244. #ifdef RT_USING_DFS_V2
  245. static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
  246. #else
  247. static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t count)
  248. #endif
  249. {
  250. int len;
  251. rt_pipe_t *pipe;
  252. int wakeup = 0;
  253. int ret = 0;
  254. uint8_t *pbuf;
  255. pipe = (rt_pipe_t *)fd->vnode->data;
  256. if (count == 0)
  257. {
  258. return 0;
  259. }
  260. pbuf = (uint8_t*)buf;
  261. rt_mutex_take(&pipe->lock, -1);
  262. while (1)
  263. {
  264. len = rt_ringbuffer_put(pipe->fifo, pbuf, count - ret);
  265. ret += len;
  266. pbuf += len;
  267. wakeup = 1;
  268. if (ret == count)
  269. {
  270. break;
  271. }
  272. else
  273. {
  274. if (fd->flags & O_NONBLOCK)
  275. {
  276. if (ret == 0)
  277. {
  278. ret = -EAGAIN;
  279. }
  280. break;
  281. }
  282. }
  283. rt_mutex_release(&pipe->lock);
  284. rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
  285. /* pipe full, waiting on suspended write list */
  286. if (rt_wqueue_wait_interruptible(&pipe->writer_queue, 0, -1) == -RT_EINTR)
  287. return -EINTR;
  288. rt_mutex_take(&pipe->lock, -1);
  289. }
  290. rt_mutex_release(&pipe->lock);
  291. if (wakeup)
  292. {
  293. rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
  294. }
  295. return ret;
  296. }
  297. /**
  298. * @brief This function will get the pipe status.
  299. *
  300. * @param fd is the file descriptor.
  301. *
  302. * @param req is the request type.
  303. *
  304. * @return mask of the pipe status.
  305. * POLLIN means there is data to be read.
  306. * POLLHUP means there is no thread that occupied the pipe to open for writing.
  307. * POLLOUT means there is space to be written.
  308. * POLLERR means there is no thread that occupied the pipe to open for reading.
  309. */
  310. static int pipe_fops_poll(struct dfs_file *fd, rt_pollreq_t *req)
  311. {
  312. int mask = 0;
  313. rt_pipe_t *pipe;
  314. int mode = 0;
  315. pipe = (rt_pipe_t *)fd->vnode->data;
  316. rt_poll_add(&pipe->reader_queue, req);
  317. rt_poll_add(&pipe->writer_queue, req);
  318. switch (fd->flags & O_ACCMODE)
  319. {
  320. case O_RDONLY:
  321. mode = 1;
  322. break;
  323. case O_WRONLY:
  324. mode = 2;
  325. break;
  326. case O_RDWR:
  327. mode = 3;
  328. break;
  329. }
  330. if (mode & 1)
  331. {
  332. if (rt_ringbuffer_data_len(pipe->fifo) != 0)
  333. {
  334. mask |= POLLIN;
  335. }
  336. else if (pipe->writer == 0)
  337. {
  338. mask = POLLHUP;
  339. }
  340. }
  341. if (mode & 2)
  342. {
  343. if (rt_ringbuffer_space_len(pipe->fifo) != 0)
  344. {
  345. mask |= POLLOUT;
  346. }
  347. }
  348. return mask;
  349. }
  350. static const struct dfs_file_ops pipe_fops =
  351. {
  352. .open = pipe_fops_open,
  353. .close = pipe_fops_close,
  354. .ioctl = pipe_fops_ioctl,
  355. .read = pipe_fops_read,
  356. .write = pipe_fops_write,
  357. .poll = pipe_fops_poll,
  358. };
  359. #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */
  360. /**
  361. * @brief This function will open the pipe and actually creates the pipe buffer.
  362. *
  363. * @param device is a pointer to the pipe device descriptor.
  364. *
  365. * @param oflag is the open method, but it is not used yet.
  366. *
  367. * @return Return the operation status.
  368. * When the return value is RT_EOK, the operation is successful.
  369. * When the return value is -RT_EINVAL, it means the device handle is empty.
  370. * When the return value is -RT_ENOMEM, it means insufficient memory allocation failed.
  371. */
  372. rt_err_t rt_pipe_open(rt_device_t device, rt_uint16_t oflag)
  373. {
  374. rt_pipe_t *pipe = (rt_pipe_t *)device;
  375. rt_err_t ret = RT_EOK;
  376. if (device == RT_NULL)
  377. {
  378. ret = -RT_EINVAL;
  379. goto __exit;
  380. }
  381. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  382. if (pipe->fifo == RT_NULL)
  383. {
  384. pipe->fifo = rt_ringbuffer_create(pipe->bufsz);
  385. if (pipe->fifo == RT_NULL)
  386. {
  387. ret = -RT_ENOMEM;
  388. }
  389. }
  390. rt_mutex_release(&pipe->lock);
  391. __exit:
  392. return ret;
  393. }
  394. /**
  395. * @brief This function will close the pipe and release the pipe buffer.
  396. *
  397. * @param device is a pointer to the pipe device descriptor.
  398. *
  399. * @return Return the operation status.
  400. * When the return value is RT_EOK, the operation is successful.
  401. * When the return value is -RT_EINVAL, it means the device handle is empty.
  402. */
  403. rt_err_t rt_pipe_close(rt_device_t device)
  404. {
  405. rt_pipe_t *pipe = (rt_pipe_t *)device;
  406. if (device == RT_NULL)
  407. {
  408. return -RT_EINVAL;
  409. }
  410. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  411. rt_ringbuffer_destroy(pipe->fifo);
  412. pipe->fifo = RT_NULL;
  413. rt_mutex_release(&pipe->lock);
  414. return RT_EOK;
  415. }
  416. /**
  417. * @brief This function will read the specified length of data from the pipe.
  418. *
  419. * @param device is a pointer to the pipe device descriptor.
  420. *
  421. * @param pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
  422. *
  423. * @param buffer is a pointer to the buffer to store the read data.
  424. *
  425. * @param count is the length of data to be read.
  426. *
  427. * @return Return the length of data read.
  428. * When the return value is 0, it means the pipe device handle is empty or the count is 0.
  429. */
  430. rt_ssize_t rt_pipe_read(rt_device_t device, rt_off_t pos, void *buffer, rt_size_t count)
  431. {
  432. uint8_t *pbuf;
  433. rt_size_t read_bytes = 0;
  434. rt_pipe_t *pipe = (rt_pipe_t *)device;
  435. if (device == RT_NULL)
  436. {
  437. rt_set_errno(-EINVAL);
  438. return 0;
  439. }
  440. if (count == 0)
  441. {
  442. return 0;
  443. }
  444. pbuf = (uint8_t*)buffer;
  445. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  446. while (read_bytes < count)
  447. {
  448. int len = rt_ringbuffer_get(pipe->fifo, &pbuf[read_bytes], count - read_bytes);
  449. if (len <= 0)
  450. {
  451. break;
  452. }
  453. read_bytes += len;
  454. }
  455. rt_mutex_release(&pipe->lock);
  456. return read_bytes;
  457. }
  458. /**
  459. * @brief This function will write the specified length of data to the pipe.
  460. *
  461. * @param device is a pointer to the pipe device descriptor.
  462. *
  463. * @param pos is a parameter compatible with POSIX standard interface (currently meaningless, just pass in 0).
  464. *
  465. * @param buffer is a pointer to the data buffer to be written.
  466. *
  467. * @param count is the length of data to be written.
  468. *
  469. * @return Return the length of data written.
  470. * When the return value is 0, it means the pipe device handle is empty or the count is 0.
  471. */
  472. rt_ssize_t rt_pipe_write(rt_device_t device, rt_off_t pos, const void *buffer, rt_size_t count)
  473. {
  474. uint8_t *pbuf;
  475. rt_size_t write_bytes = 0;
  476. rt_pipe_t *pipe = (rt_pipe_t *)device;
  477. if (device == RT_NULL)
  478. {
  479. rt_set_errno(-EINVAL);
  480. return 0;
  481. }
  482. if (count == 0)
  483. {
  484. return 0;
  485. }
  486. pbuf = (uint8_t*)buffer;
  487. rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
  488. while (write_bytes < count)
  489. {
  490. int len = rt_ringbuffer_put(pipe->fifo, &pbuf[write_bytes], count - write_bytes);
  491. if (len <= 0)
  492. {
  493. break;
  494. }
  495. write_bytes += len;
  496. }
  497. rt_mutex_release(&pipe->lock);
  498. return write_bytes;
  499. }
  500. /**
  501. * @brief This function is not used yet.
  502. *
  503. * @param dev is not used yet.
  504. *
  505. * @param cmd is not used yet.
  506. *
  507. * @param args is not used yet.
  508. *
  509. * @return Always return RT_EOK.
  510. */
  511. rt_err_t rt_pipe_control(rt_device_t dev, int cmd, void *args)
  512. {
  513. return RT_EOK;
  514. }
  515. #ifdef RT_USING_DEVICE_OPS
  516. const static struct rt_device_ops pipe_ops =
  517. {
  518. RT_NULL,
  519. rt_pipe_open,
  520. rt_pipe_close,
  521. rt_pipe_read,
  522. rt_pipe_write,
  523. rt_pipe_control,
  524. };
  525. #endif /* RT_USING_DEVICE_OPS */
  526. /**
  527. * @brief This function will initialize a pipe device.
  528. * The system allocates a pipe handle from dynamic heap memory, initializes the pipe handle
  529. * with the specified value, and registers the pipe device with the system.
  530. *
  531. * @param name is the name of pipe device.
  532. *
  533. * @param bufsz is the size of pipe buffer.
  534. *
  535. * @return Return the pointer to the pipe device.
  536. * When the return value is RT_NULL, it means the initialization failed.
  537. */
  538. rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
  539. {
  540. rt_pipe_t *pipe;
  541. rt_device_t dev;
  542. RT_ASSERT(name != RT_NULL);
  543. RT_ASSERT(bufsz < 0xFFFF);
  544. if (rt_device_find(name) != RT_NULL)
  545. {
  546. /* pipe device has been created */
  547. return RT_NULL;
  548. }
  549. pipe = (rt_pipe_t *)rt_malloc(sizeof(rt_pipe_t));
  550. if (pipe == RT_NULL) return RT_NULL;
  551. rt_memset(pipe, 0, sizeof(rt_pipe_t));
  552. pipe->is_named = RT_TRUE; /* initialize as a named pipe */
  553. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
  554. pipe->pipeno = -1;
  555. #endif
  556. rt_mutex_init(&pipe->lock, name, RT_IPC_FLAG_FIFO);
  557. rt_wqueue_init(&pipe->reader_queue);
  558. rt_wqueue_init(&pipe->writer_queue);
  559. rt_condvar_init(&pipe->waitfor_parter, "piwfp");
  560. pipe->writer = 0;
  561. pipe->reader = 0;
  562. pipe->bufsz = bufsz;
  563. dev = &pipe->parent;
  564. dev->type = RT_Device_Class_Pipe;
  565. #ifdef RT_USING_DEVICE_OPS
  566. dev->ops = &pipe_ops;
  567. #else
  568. dev->init = RT_NULL;
  569. dev->open = rt_pipe_open;
  570. dev->read = rt_pipe_read;
  571. dev->write = rt_pipe_write;
  572. dev->close = rt_pipe_close;
  573. dev->control = rt_pipe_control;
  574. #endif
  575. dev->rx_indicate = RT_NULL;
  576. dev->tx_complete = RT_NULL;
  577. rt_device_register(&pipe->parent, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
  578. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
  579. dev->fops = (void *)&pipe_fops;
  580. #endif
  581. return pipe;
  582. }
  583. /**
  584. * @brief This function will delete a pipe device.
  585. * The system will release the pipe handle and unregister the pipe device from the system.
  586. *
  587. * @param pipe is the pointer to the pipe device.
  588. *
  589. * @return Return the operation status.
  590. * When the return value is 0, it means the operation is successful.
  591. * When the return value is -RT_EINVAL, it means the pipe device is not found or the device isn't a pipe.
  592. * When the return value is -RT_EBUSY, it means the pipe device is busy.
  593. */
  594. int rt_pipe_delete(const char *name)
  595. {
  596. int result = 0;
  597. rt_device_t device;
  598. device = rt_device_find(name);
  599. if (device)
  600. {
  601. if (device->type == RT_Device_Class_Pipe)
  602. {
  603. rt_pipe_t *pipe;
  604. pipe = (rt_pipe_t *)device;
  605. rt_condvar_detach(&pipe->waitfor_parter);
  606. rt_mutex_detach(&pipe->lock);
  607. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
  608. resource_id_put(&id_mgr, pipe->pipeno);
  609. #endif
  610. rt_device_unregister(device);
  611. /* close fifo ringbuffer */
  612. if (pipe->fifo)
  613. {
  614. rt_ringbuffer_destroy(pipe->fifo);
  615. pipe->fifo = RT_NULL;
  616. }
  617. rt_free(pipe);
  618. }
  619. else
  620. {
  621. result = -ENODEV;
  622. }
  623. }
  624. else
  625. {
  626. result = -ENODEV;
  627. }
  628. return result;
  629. }
  630. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
  631. /**
  632. * @brief This function will creat a anonymous pipe.
  633. *
  634. * @param fildes[0] is the read handle.
  635. * fildes[1] is the write handle.
  636. *
  637. * @return Return the operation status.
  638. * When the return value is 0, it means the operation is successful.
  639. * When the return value is -1, it means the operation is failed.
  640. */
  641. int pipe(int fildes[2])
  642. {
  643. rt_pipe_t *pipe;
  644. char dname[8];
  645. char dev_name[32];
  646. int pipeno = 0;
  647. pipeno = resource_id_get(&id_mgr);
  648. if (pipeno == -1)
  649. {
  650. return -1;
  651. }
  652. rt_snprintf(dname, sizeof(dname), "pipe%d", pipeno);
  653. pipe = rt_pipe_create(dname, RT_USING_POSIX_PIPE_SIZE);
  654. if (pipe == RT_NULL)
  655. {
  656. resource_id_put(&id_mgr, pipeno);
  657. return -1;
  658. }
  659. pipe->is_named = RT_FALSE; /* unamed pipe */
  660. pipe->pipeno = pipeno;
  661. rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
  662. fildes[1] = open(dev_name, O_WRONLY, 0);
  663. if (fildes[1] < 0)
  664. {
  665. rt_pipe_delete(dname);
  666. return -1;
  667. }
  668. fildes[0] = open(dev_name, O_RDONLY, 0);
  669. if (fildes[0] < 0)
  670. {
  671. close(fildes[1]);
  672. rt_pipe_delete(dname);
  673. return -1;
  674. }
  675. return 0;
  676. }
  677. /**
  678. * @brief This function will create a named pipe.
  679. *
  680. * @param path is the name of pipe device.
  681. *
  682. * @param mode is not used yet.
  683. *
  684. * @return Return the operation status.
  685. * When the return value is 0, it means the operation is successful.
  686. * When the return value is -1, it means the operation is failed.
  687. */
  688. int mkfifo(const char *path, mode_t mode)
  689. {
  690. rt_pipe_t *pipe;
  691. pipe = rt_pipe_create(path, RT_USING_POSIX_PIPE_SIZE);
  692. if (pipe == RT_NULL)
  693. {
  694. return -1;
  695. }
  696. return 0;
  697. }
  698. #endif /* defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE) */