Access GPIO from Linux user space

GPIO mean "General Purpose Input/Output" and is a special pin present in some chip that can be set as input or output and used to move a signal high or low (in output mode) or to get the signal current status (in input mode). Usually these pin are directly managed by kernel modules but there are an easy way to manage these pins also from user space.

Standard Linux kernel have inside a special interface allow to access to GPIO pins. Once executed kernel menuconfig you can easily verify is this interface is active in your kernel and, in case, enable them. The kernel tree path is the following:

Device Drivers  ---> GPIO Support  ---> /sys/class/gpio/... (sysfs interface)

If not, enable this feature and recompile the kernel before continue to read. The interface to allow working with GPIO is at the following filesystem path:


Basically if you want to work with a particular GPIO you must first to reserve it, set the input/output direction and start managing it. Once you reserved the GPIO and finished to use you need to free it for allow other modules or process to use them. This rule is valid in both cases you want to use GPIO from kernel level or user level.

Manage GPIO from command line or script

From the user level side this "operation" for reserve the GPIO is called "export" the GPIO. For make this export operation you simply need to echo the GPIO number you are interested to a special path as follow (change XX with the GPIO number you need):

echo XX > /sys/class/gpio/export

If operation successful (the possible case of operation failed is explained below) a new "folder" will show up in the GPIO interface path as example below:


This new "folder" will allow you to work with the GPIO you just reserved. In particular if you want to set the in/out direction you simply need to execute the following echo commands:

echo "out" > /sys/class/gpio/gpioXX/direction


echo "in" > /sys/class/gpio/gpioXX/direction

In case you set out direction you can directly manage the value of GPIO. You can make this operation by executing additional echo commands like:

echo 1 > /sys/class/gpio/gpioXX/value


echo 0 > /sys/class/gpio/gpioXX/value

Since GPIO is a single pin the possible states allowed are high (1) and low (0). In case you set in direction you can read the current pin value by using the following command:

cat /sys/class/gpio/gpioXX/value

Once finished to use your GPIO you can free it by make the same echo command but to different path:

echo XX > /sys/class/gpio/unexport

In case of GPIO folder not showed after export operation is very likely that the GPIO is already reserved by some module. For verify the current reserved GPIO map you must first verify if in your kernel is enabled the following feature:

Kernel configuration ---> Kernel hacking ---> Debug FS

As usual, if not enabled, enable it and recompile the kernel. The next step is to launch the following command line for mount debugfs:

mount -t debugfs none /sys/kernel/debug

and dump the current GPIO configuration by using:

cat /sys/kernel/debug/gpio

The output will show you the current list og reserved GPIO.

Manage GPIO from application

All these same operations can be made using a software application. Follow short lines of C code showing how the reproduce the same steps as above (remember to change XX with the GPIO number you want to use).

Reserve (export) the GPIO:

int fd;
char buf[MAX_BUF]; 
int gpio = XX;

fd = open("/sys/class/gpio/export", O_WRONLY);

sprintf(buf, "%d", gpio); 

write(fd, buf, strlen(buf));


Set the direction in the GPIO folder just created:

sprintf(buf, "/sys/class/gpio/gpio%d/direction", gpio);

fd = open(buf, O_WRONLY);

// Set out direction
write(fd, "out", 3); 
// Set in direction
write(fd, "in", 2); 


In case of out direction set the value of GPIO:

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_WRONLY);

// Set GPIO high status
write(fd, "1", 1); 
// Set GPIO low status 
write(fd, "0", 1); 


In case of in direction get the current value of GPIO:

char value;

sprintf(buf, "/sys/class/gpio/gpio%d/value", gpio);

fd = open(buf, O_RDONLY);

read(fd, &value, 1);

if(value == '0')
     // Current GPIO status low
     // Current GPIO status high


Once finished free (unexport) the GPIO:

fd = open("/sys/class/gpio/unexport", O_WRONLY);

sprintf(buf, "%d", gpio);

write(fd, buf, strlen(buf));


An important note you have to keep in mind if you plan to set or, more important, get the value of a GPIO through this way in continous mode. If you open the "value" file for get the current GPIO status (1 or 0) remember that, after the fist read operation, the file pointer will move to the next position in the file. Since this interface was made to be read from cat command the returned string will be terminated by the new line character (\n). This mean after the first "valid" read all the next read operation will return always the last character in the file, in this case only the new line '\n'. For obtain a correct status value for each read operation you simply have to set the file pointer at the beginning of the file before read by using the command below:

lseek(fp, 0, SEEK_SET);

You will not have this problem if you open and close GPIO value file every time you need to read but, as you can know, for continuous read introduce a short delay. Since these short lines of codes are only an example if you want to use them in your code remember add the control for error in open GPIO file.


Awesome :)

June 27, 2013 at 11:24 PM comment-delete

really good article........thanks

July 19, 2013 at 3:23 AM comment-delete

really good .. thanks

July 21, 2013 at 7:33 AM comment-delete

Okay. I dont see no userland. All operations need root.

August 15, 2013 at 5:55 AM comment-delete

Cat /sys/class/gpio/gpioXX/value always prints 0 on my board. But when I use a voltage meter it shows the correct voltage.

September 12, 2013 at 4:10 AM comment-delete

These gpio devices are not always automatic generated. You need to configure or "patch" the kernel for allow them to work as expected.

September 12, 2013 at 12:47 PM comment-delete

Is there a good way to produce interrupts / or use blocking reads?(fread for example). Cause polling will kill the performance from my application

November 6, 2013 at 7:58 AM comment-delete

Surely not at user level. You need to develop your own module running at kernel level for manage interrupt. Regarding the possibilty to have interrupt connected to gpio it depends from your hardware. If the cpu will allow it you'll have to configure it as indicated by datasheet.

November 6, 2013 at 9:22 AM comment-delete

Great, Thanks...

February 7, 2014 at 3:27 AM comment-delete

If a GPIO is already reserved, how can I control it from userspace?

February 20, 2014 at 2:24 AM comment-delete

Sorry, if the GPIO is reserved by someone else you can not use it...

February 20, 2014 at 3:13 AM comment-delete

Ok, thanks!

February 20, 2014 at 3:50 AM comment-delete

Super-helpful article--thanks!

March 16, 2014 at 11:13 AM comment-delete

Greattt!!!!!!!!! THNKS!!

May 15, 2014 at 11:34 AM comment-delete

useful information. Thanks

May 29, 2014 at 2:01 AM comment-delete

thanks. very helpful to all.:)

June 8, 2014 at 10:37 PM comment-delete

Really useful information, Thanks.
But can you please tell me, How to access GPIO from kernel space?

June 12, 2014 at 10:01 PM comment-delete

Kernel space have a different set of functions available for manage GPIO. Some of them are:

int gpio_request(unsigned int gpio, const char *label);
void gpio_free(unsigned int gpio);
int gpio_direction_input(unsigned int gpio);
int gpio_direction_output(unsigned int gpio, int value);
int gpio_get_value(unsigned int gpio);
void gpio_set_value(unsigned int gpio, int value);

You can find more details googling around...

June 12, 2014 at 11:56 PM comment-delete


October 10, 2014 at 2:55 AM comment-delete

i have a problem: i can correctly use the GPIO using shell scripts, but i can't do it using a software application in C. The problem it that i can't open the */value and */direction files.

October 11, 2014 at 3:24 AM comment-delete

Sorry but you need to check the error code generated by the open fail operation.

October 11, 2014 at 8:49 AM comment-delete

can you help me?
i have a raspberry pi b + as a webserver, i can remotely get to it, push the button and i get 2 errors in the apache log files, permissions denied and premature end of script. i dont know if i have a httpd.conf file and i dont know if i need to change something in .htaccess but also please tell me real fast, if this set01.cgi script looks ok

echo "1" > /sys/class/gpio/gpio4/value

January 4, 2015 at 11:23 AM comment-delete

httpd.conf and .htaccess doesn't seem to be connected to the gpio access. The error "permission denied" mean your script is executed under some user that doesn't have enough privileges to access gpio fields. The easiest solution in this case is to "extened" permission of "/sys/class/gpio/gpio4/value" to the user or the group you currently run your script (using chmod command in server side).

January 5, 2015 at 9:27 PM comment-delete

Great article!

January 8, 2015 at 4:34 PM comment-delete

good job!

April 24, 2015 at 9:43 PM comment-delete

Great job! Thanks for article!

May 7, 2015 at 1:19 AM comment-delete

Really useful informations, thank you !

June 12, 2015 at 12:43 AM comment-delete

How do I set GPIO66 and GPIO68 for PWM use?

June 17, 2015 at 2:43 PM comment-delete

Hi all,

In my kernel it shows like that :

root@ls2085aqds:/sys/class/gpio# ls
export gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport
root@ls2085aqds:/sys/class/gpio# echo 224 > export
export_store: invalid GPIO 224
-sh: echo: write error: Invalid argument

Actually i need to toggle the GPIO2_24 th pin. I don't know how to access that pin and how to toggle that pin. can you help me please..?


June 18, 2015 at 12:33 AM comment-delete

Label GPIO2_24 doesn't not automatically mean the GPIO number is 224. You have to check your hardware datasheet or how your kernel internally manage to number the GPIO you need...

June 18, 2015 at 12:46 AM comment-delete

@Russ M: this post explain the standard direct interface for access GPIO from user space. PWM, for what I know, is another type of interface so I guess you need to manage the GPIO internally to kernel if you want to use PWM interface (but I'm not expert in using it than I'm not sure about that).

June 18, 2015 at 12:49 AM comment-delete

how to continuously call the show function in sysfs by using c user program

June 18, 2015 at 3:14 AM comment-delete

Excellent article. How can I find out which module has reserved a reserved gpio.
I executed "cat /sys/kernel/debug/gpio". I have posted a portion of the output below.
GPIOs 148-178, GPH:
gpio-162 (? ) in lo
gpio-163 (? ) in lo
gpio-164 (? ) in lo
gpio-165 (? ) in lo

Please help.

June 18, 2015 at 11:17 PM comment-delete

Sorry but I don't know if there is a way to know which module reserved GPIO, neved had this problem and currently I don't know how to help you...

June 20, 2015 at 2:18 AM comment-delete

Hi all,

In my kernel gpio directory it shows like that

sys/class/gpio# ls
export gpiochip384 gpiochip416 gpiochip448 gpiochip480 unexport

here wt is the gpiochip384, 416, 448, 480 and how they are enabled here?

July 7, 2015 at 10:51 PM comment-delete

Sorry, don't understand the question, what does it mean "how they are enabled here"? Remeber GPIO export operation can be "requested" not only by user space as described in this post but also internally by some kernel module itself...

July 8, 2015 at 1:30 AM comment-delete

In my kernel gpio directory shows gpiochip384, gpiochip416, gpiochip448, gpiochip480.

I think
gpiochip384 - GPIO1
gpiochip416 - GPIO2
gpiochip448 - GPIO3
gpiochip480 - GPIO4

I need to toggle one gpio pin ex.gpio4_24 (480+24=504)

for that i need to echo 504 > export right..?

i dont kw if its correct or wrong.. can u correct me pls..?

July 8, 2015 at 5:08 AM comment-delete


The problem here is only to know how to "calculate" the correct GPIO number based to your hardware. I don't know if your calculation is correct since it depends by the chipset you are working on. You have to check the datasheet of the chipset for know if the GPIO number is correct. Once got the correct number the export procedure is the same.

July 8, 2015 at 11:52 PM comment-delete

For iMX6 to calculate which GPIO you need to export you can refer to :

August 8, 2015 at 9:27 PM comment-delete

When i enter the command:
sudo echo "17" > /sys/class/gpio/export
i get the message:
-bash: /sys/class/gpio/export: Permission denied
Why is that?

September 25, 2015 at 10:58 AM comment-delete

You need to have root privileges for make this operation. From the error message it seem you don't have...

September 25, 2015 at 11:18 AM comment-delete

hi very useful article.
i have a question
in my kernel i have :GPIO 18 --> SDA and GPIO 19--> SCL
how can i change the GPIOS to be :GPIO 19 --> SDA and GPIO 18--> SCL


October 13, 2015 at 3:23 AM comment-delete

Teorically you can't since usually GPIO are physically harware mapped and the kernel report this mapping status. The only way I can see is to patch the kernel GPIO driver to make an "software inversion" but it would not be a good idea in any case. Please note if you want to manage an I2C bus communication from user space using kernel GPIO interface the communication will be really slow...

October 13, 2015 at 4:58 AM comment-delete

thanks for your apply.
how can i make that ?
have you any information or tutorials ??

October 13, 2015 at 8:07 AM comment-delete

The kernel is "customized" to work on your hardware. Maybe it will be possible to find some general tutorial (however I don't know) but the only way you have is to look into your kernel sources for find the module involved in GPIO communication with your hardware. Once found work on it.

October 15, 2015 at 12:04 AM comment-delete

Thanks a lot,

January 29, 2016 at 8:29 AM comment-delete

Simply Super

April 6, 2016 at 11:10 PM comment-delete

thanks for this valuable article
i used the following commands to access the gpio on SAM9G25 microcontroller:
#echo 66 > /sys/class/gpio/export
#echo in > /sys/class/gpio/gpio66/direction
#cat /sys/class/gpio/gpio66/value
these commands run successfully on a linux with kernel version 3.6.9
it doesn't work on the same development kit when I run emdebian with kernel version 3.11.6
I got
#echo in > /sys/class/gpio/gpio66/direction
-bash: /sys/class/gpio/gpio66/direction: No such file or directory

April 13, 2016 at 2:49 AM comment-delete

Kernel need to be "configured" to manage correctly specific board GPIO and expose them through gpio module interface. Required configuration can come from kernel board pinmuxing map, gpio module configuration and so on, I can not know the reasons, you have to check and configure correctly the kernel you plan to use for your project based to your hardware...

April 13, 2016 at 3:34 AM comment-delete

I hv this GPIO debugging too:
root@core9g25:~# cat /sys/kernel/debug/gpio
GPIOs 0-31, platform/fffff400.gpio, fffff400.gpio:
[w1] GPIOfffff400.gpio21: [gpio] set
GPIOs 32-50, platform/fffff600.gpio, fffff600.gpio:
[aria_led] GPIOfffff600.gpio8: [periph A]
GPIOs 64-95, platform/fffff800.gpio, fffff800.gpio:
GPIOs 96-117, platform/fffffa00.gpio, fffffa00.gpio:

April 13, 2016 at 5:53 AM comment-delete

thank you

April 13, 2016 at 9:17 AM comment-delete

Great article!!! it helped me a lot!!

Hey do you have something similar but for i2c?

May 20, 2016 at 9:02 AM comment-delete

Thank you for the comment. About i2c didn't write anything because is already possible to found some good aricle around than I thought there was no need. Maybe I'll write something in the future... ^_^

May 22, 2016 at 5:31 AM comment-delete


Great article.... helped me a lot for lemaker board. Recently only i started working on linux on lemaker board. now i am trying for interrupts, but i am not getting ..please guide me for complete interrupt part. led blinking need to do with switch in interrupt method.

Thank you.

November 24, 2016 at 5:35 AM comment-delete

This article explain how to manage with GPIO from user space but infortunately is not possible manage interrupts from user space. The only way is to develop a kernel driver. There is a free book titled "Linux device drivers" that you can read about develop your driver.

November 24, 2016 at 7:08 AM comment-delete


i found your article very helpful thanks for writing it. I want to blink the leds on the zed board, so when i tried the method the gpioxx folder is not created for me so i tried mount -t debugfs none /sys/kernel/debug but found that there is no debud folder in the kernel....
any help will be appreciated.

November 28, 2016 at 5:22 AM comment-delete

As written in the post have you verified the following feature is enabled on the kernel config?

Kernel configuration ---> Kernel hacking ---> Debug FS

Remember if you enable it you have to recompile the entire kernel for get it working.

November 28, 2016 at 7:28 AM comment-delete

so in the kernel hacking there was no Debug FS in the list...

November 28, 2016 at 11:14 AM comment-delete

There is no debug fs in kernel hacking but instead
Device drivers--> gpio support --> sys/class/gpio... (sys interface)
Which is selected

November 29, 2016 at 12:28 AM comment-delete

Unfortunately linux kernel continuously change in structure based on distribution and so on. If you don't get your GPIO probably mean some driver reserved it or the use of that GPIO is not configured in your kernel. Kernel for ARM have to be configured through specific configuration files instructing the kernel itself about available devices in specific hardware. I can not help you in this case since variants can be infinite, you have to look into your kernel sources for try to understand why this specific GPIO is not allowed to be exported...

November 29, 2016 at 1:36 AM comment-delete

yeah so i found out the debus fs it was in

kernel configuration-->kernel hacking -->compile time checks and compile options-->debug fs

but now it seems like the gpio is reserved and i cannot use it.
i tried to mount it as
mount -t sysfs sysfs /sys
but it doesnt let me.

November 29, 2016 at 2:05 AM comment-delete

Why "mount -t sysfs sysfs /sys"? The correct path for mount is "mount -t debugfs none /sys/kernel/debug". However keep in mind that you'll probably have to change something in the kernel code to have your GPIO available from user space...

November 30, 2016 at 12:03 AM comment-delete

Post a Comment